From 22b412f880b41651d4e8718f108d0c30b832b73a Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 24 May 2015 13:01:39 +0000 Subject: [PATCH 001/204] HttpClient 4.5.x branch git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1681444 13f79535-47bb-0310-9956-ffa450edef68 From 1fc51847e7ba824ef8d0616b9d16b2861a9978f9 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 26 May 2015 18:59:46 +0000 Subject: [PATCH 002/204] HTTPCLIENT-1650: fluent Executor to create a local CredentialsProvide instance only if credentials are explicitly set git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1681815 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/client/fluent/Executor.java | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Executor.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Executor.java index fa2184b7c2..187cf89587 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Executor.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Executor.java @@ -111,19 +111,28 @@ public static Executor newInstance(final HttpClient httpclient) { } private final HttpClient httpclient; - private final AuthCache authCache; - private final CredentialsProvider credentialsProvider; - + private volatile AuthCache authCache; + private volatile CredentialsProvider credentialsProvider; private volatile CookieStore cookieStore; Executor(final HttpClient httpclient) { super(); this.httpclient = httpclient; - this.credentialsProvider = new BasicCredentialsProvider(); this.authCache = new BasicAuthCache(); } + /** + * @since 4.5 + */ + public Executor use(final CredentialsProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + return this; + } + public Executor auth(final AuthScope authScope, final Credentials creds) { + if (this.credentialsProvider == null) { + this.credentialsProvider = new BasicCredentialsProvider(); + } this.credentialsProvider.setCredentials(authScope, creds); return this; } @@ -200,17 +209,33 @@ public Executor auth(final HttpHost host, } public Executor clearAuth() { - this.credentialsProvider.clear(); + if (this.credentialsProvider != null) { + this.credentialsProvider.clear(); + } return this; } + /** + * @deprecated (4.5) Use {@link #use(CookieStore)}. + */ + @Deprecated public Executor cookieStore(final CookieStore cookieStore) { this.cookieStore = cookieStore; return this; } + /** + * @since 4.5 + */ + public Executor use(final CookieStore cookieStore) { + this.cookieStore = cookieStore; + return this; + } + public Executor clearCookies() { - this.cookieStore.clear(); + if (this.cookieStore != null) { + this.cookieStore.clear(); + } return this; } @@ -225,9 +250,15 @@ public Executor clearCookies() { public Response execute( final Request request) throws ClientProtocolException, IOException { final HttpClientContext localContext = HttpClientContext.create(); - localContext.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider); - localContext.setAttribute(HttpClientContext.AUTH_CACHE, this.authCache); - localContext.setAttribute(HttpClientContext.COOKIE_STORE, this.cookieStore); + if (this.credentialsProvider != null) { + localContext.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider); + } + if (this.authCache != null) { + localContext.setAttribute(HttpClientContext.AUTH_CACHE, this.authCache); + } + if (this.cookieStore != null) { + localContext.setAttribute(HttpClientContext.COOKIE_STORE, this.cookieStore); + } return new Response(request.internalExecute(this.httpclient, localContext)); } From 0ad9857ed81747249f710c6519a638d3b0b6a5d0 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 27 May 2015 14:22:21 +0000 Subject: [PATCH 003/204] Fixed regresson in a deprecated method of FileBody Contributed by Andrey Pohilko git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682040 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/entity/mime/content/FileBody.java | 2 +- .../http/entity/mime/FormBodyPartTest.java | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 httpmime/src/test/java/org/apache/http/entity/mime/FormBodyPartTest.java diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/content/FileBody.java b/httpmime/src/main/java/org/apache/http/entity/mime/content/FileBody.java index 877dcc4462..9236fe915a 100644 --- a/httpmime/src/main/java/org/apache/http/entity/mime/content/FileBody.java +++ b/httpmime/src/main/java/org/apache/http/entity/mime/content/FileBody.java @@ -96,7 +96,7 @@ public FileBody(final File file, final ContentType contentType, final String fil super(contentType); Args.notNull(file, "File"); this.file = file; - this.filename = filename; + this.filename = filename == null ? file.getName() : filename; } /** diff --git a/httpmime/src/test/java/org/apache/http/entity/mime/FormBodyPartTest.java b/httpmime/src/test/java/org/apache/http/entity/mime/FormBodyPartTest.java new file mode 100644 index 0000000000..5f7f5c06cd --- /dev/null +++ b/httpmime/src/test/java/org/apache/http/entity/mime/FormBodyPartTest.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.entity.mime; + +import org.apache.http.entity.mime.content.FileBody; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; + +public class FormBodyPartTest { + + @Test + public void testConstructorCompat() throws Exception { + final File tmp= File.createTempFile("test", "test"); + tmp.deleteOnExit(); + final FileBody obj=new FileBody(tmp, "application/octet-stream"); + Assert.assertEquals(tmp.getName(), obj.getFilename()); + } +} \ No newline at end of file From ed396445436a0c30cd9e078e2cea1298ac595c6d Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Thu, 28 May 2015 13:47:24 +0000 Subject: [PATCH 004/204] Fixed typo in exception message git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682244 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/client/protocol/ResponseContentEncoding.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java index 9e4c19aea0..9cb4adbbec 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java @@ -143,7 +143,7 @@ public void process( response.removeHeaders("Content-MD5"); } else { if (!"identity".equals(codecname) && !ignoreUnknown) { - throw new HttpException("Unsupported Content-Coding: " + codec.getName()); + throw new HttpException("Unsupported Content-Encoding: " + codec.getName()); } } } From 6cd90f89bef50517312e7d027ea6094821566480 Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Sat, 30 May 2015 19:38:50 +0000 Subject: [PATCH 005/204] HTTPCLIENT-1651: Add ability to disable content compression on a request basis git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682646 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/client/config/RequestConfig.java | 33 ++++++++++++++++--- .../protocol/RequestAcceptEncoding.java | 6 +++- .../http/client/config/TestRequestConfig.java | 3 ++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java index c3b707152c..08c27a1b77 100644 --- a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java +++ b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java @@ -59,12 +59,13 @@ public class RequestConfig implements Cloneable { private final int connectTimeout; private final int socketTimeout; private final boolean decompressionEnabled; + private final boolean contentCompressionEnabled; /** * Intended for CDI compatibility */ protected RequestConfig() { - this(false, null, null, false, null, false, false, false, 0, false, null, null, 0, 0, 0, false); + this(false, null, null, false, null, false, false, false, 0, false, null, null, 0, 0, 0, false, false); } RequestConfig( @@ -83,7 +84,8 @@ protected RequestConfig() { final int connectionRequestTimeout, final int connectTimeout, final int socketTimeout, - final boolean decompressionEnabled) { + final boolean decompressionEnabled, + final boolean contentCompressionEnabled) { super(); this.expectContinueEnabled = expectContinueEnabled; this.proxy = proxy; @@ -101,6 +103,7 @@ protected RequestConfig() { this.connectTimeout = connectTimeout; this.socketTimeout = socketTimeout; this.decompressionEnabled = decompressionEnabled; + this.contentCompressionEnabled = contentCompressionEnabled; } /** @@ -317,6 +320,18 @@ public boolean isDecompressionEnabled() { return decompressionEnabled; } + /** + * Determines whether the target server is requested to compress content. + *

+ * Default: {@code true} + *

+ * + * @since 4.5 + */ + public boolean isContentCompressionEnabled() { + return contentCompressionEnabled; + } + @Override protected RequestConfig clone() throws CloneNotSupportedException { return (RequestConfig) super.clone(); @@ -341,6 +356,7 @@ public String toString() { builder.append(", connectTimeout=").append(connectTimeout); builder.append(", socketTimeout=").append(socketTimeout); builder.append(", decompressionEnabled=").append(decompressionEnabled); + builder.append(", contentCompressionEnabled=").append(contentCompressionEnabled); builder.append("]"); return builder.toString(); } @@ -367,7 +383,8 @@ public static RequestConfig.Builder copy(final RequestConfig config) { .setConnectionRequestTimeout(config.getConnectionRequestTimeout()) .setConnectTimeout(config.getConnectTimeout()) .setSocketTimeout(config.getSocketTimeout()) - .setDecompressionEnabled(config.isDecompressionEnabled()); + .setDecompressionEnabled(config.isDecompressionEnabled()) + .setContentCompressionEnabled(config.isContentCompressionEnabled()); } public static class Builder { @@ -388,6 +405,7 @@ public static class Builder { private int connectTimeout; private int socketTimeout; private boolean decompressionEnabled; + private boolean contentCompressionEnabled; Builder() { super(); @@ -400,6 +418,7 @@ public static class Builder { this.connectTimeout = -1; this.socketTimeout = -1; this.decompressionEnabled = true; + this.contentCompressionEnabled = true; } public Builder setExpectContinueEnabled(final boolean expectContinueEnabled) { @@ -487,6 +506,11 @@ public Builder setDecompressionEnabled(final boolean decompressionEnabled) { return this; } + public Builder setContentCompressionEnabled(final boolean contentCompressionEnabled) { + this.contentCompressionEnabled = contentCompressionEnabled; + return this; + } + public RequestConfig build() { return new RequestConfig( expectContinueEnabled, @@ -504,7 +528,8 @@ public RequestConfig build() { connectionRequestTimeout, connectTimeout, socketTimeout, - decompressionEnabled); + decompressionEnabled, + contentCompressionEnabled); } } diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java index 9209ac8b7b..9b260e2066 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java @@ -33,6 +33,7 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.annotation.Immutable; +import org.apache.http.client.config.RequestConfig; import org.apache.http.protocol.HttpContext; /** @@ -76,8 +77,11 @@ public void process( final HttpRequest request, final HttpContext context) throws HttpException, IOException { + final HttpClientContext clientContext = HttpClientContext.adapt(context); + final RequestConfig requestConfig = clientContext.getRequestConfig(); + /* Signal support for Accept-Encoding transfer encodings. */ - if (!request.containsHeader("Accept-Encoding")) { + if (!request.containsHeader("Accept-Encoding") && requestConfig.isContentCompressionEnabled()) { request.addHeader("Accept-Encoding", acceptEncoding); } } diff --git a/httpclient/src/test/java/org/apache/http/client/config/TestRequestConfig.java b/httpclient/src/test/java/org/apache/http/client/config/TestRequestConfig.java index f37f64d244..68c70fc8b3 100644 --- a/httpclient/src/test/java/org/apache/http/client/config/TestRequestConfig.java +++ b/httpclient/src/test/java/org/apache/http/client/config/TestRequestConfig.java @@ -59,6 +59,7 @@ public void testDefaults() { Assert.assertEquals(null, config.getProxy()); Assert.assertEquals(null, config.getTargetPreferredAuthSchemes()); Assert.assertEquals(null, config.getProxyPreferredAuthSchemes()); + Assert.assertEquals(true, config.isContentCompressionEnabled()); } @Test @@ -78,6 +79,7 @@ public void testBuildAndCopy() throws Exception { .setProxy(new HttpHost("someproxy")) .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM)) .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.DIGEST)) + .setContentCompressionEnabled(false) .build(); final RequestConfig config = RequestConfig.copy(config0).build(); Assert.assertEquals(22, config.getSocketTimeout()); @@ -94,6 +96,7 @@ public void testBuildAndCopy() throws Exception { Assert.assertEquals(new HttpHost("someproxy"), config.getProxy()); Assert.assertEquals(Arrays.asList(AuthSchemes.NTLM), config.getTargetPreferredAuthSchemes()); Assert.assertEquals(Arrays.asList(AuthSchemes.DIGEST), config.getProxyPreferredAuthSchemes()); + Assert.assertEquals(false, config.isContentCompressionEnabled()); } } From 8501cb9b0c029fb488a7701a11513ce789422105 Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Sat, 30 May 2015 19:43:22 +0000 Subject: [PATCH 006/204] git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682647 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 362 +++++++++++++++++++++++----------------------- 1 file changed, 182 insertions(+), 180 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 8cc7589284..e0fdcfc8ae 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -25,6 +25,8 @@ Changelog: * [HTTPCLIENT-1613]: Support for private domains in Mozilla Public Suffix List. Contributed by Oleg Kalnichevski +* [HTTPCLIENT-1651]: Add ability to disable content compression on a request basis + Contributed by Michael Osipov Release 4.4.1 @@ -61,18 +63,18 @@ Release 4.4 Final This is the first stable (GA) release of HttpClient 4.4. Notable features and enhancements included in 4.4 series are: -* Support for the latest HTTP state management specification (RFC 6265). Please note that the old -cookie policy is still used by default for compatibility reasons. RFC 6265 compliant cookie -policies need to be explicitly configured by the user. Please also note that as of next feature -release support for Netscape draft, RFC 2109 and RFC 2965 cookie policies will be deprecated -and disabled by default. It is recommended to use RFC 6265 compliant policies for new applications -unless compatibility with RFC 2109 and RFC 2965 is required and to migrate existing applications +* Support for the latest HTTP state management specification (RFC 6265). Please note that the old +cookie policy is still used by default for compatibility reasons. RFC 6265 compliant cookie +policies need to be explicitly configured by the user. Please also note that as of next feature +release support for Netscape draft, RFC 2109 and RFC 2965 cookie policies will be deprecated +and disabled by default. It is recommended to use RFC 6265 compliant policies for new applications +unless compatibility with RFC 2109 and RFC 2965 is required and to migrate existing applications to the default cookie policy. * Enhanced, redesigned and rewritten default SSL hostname verifier with improved RFC 2818 compliance -* Default SSL hostname verifier and default cookie policy now validate certificate identity +* Default SSL hostname verifier and default cookie policy now validate certificate identity and cookie domain of origin against the public suffix list maintained by Mozilla.org @@ -103,28 +105,28 @@ Changelog: Contributed by Oleg Kalnichevski * [HTTPCLIENT-1515] Caching of responses to HEAD requests - Contributed by Tyrone Cutajar and - Francois-Xavier Bonnet + Contributed by Tyrone Cutajar and + Francois-Xavier Bonnet * [HTTPCLIENT-1560] Native Windows auth improvements Contributed by Michael Osipov -* Update Apache Commons Logging version from 1.1.3 to 1.2. +* Update Apache Commons Logging version from 1.1.3 to 1.2. Contributed by Gary Gregory -* Update Apache Commons Codec version from 1.6 to 1.9. +* Update Apache Commons Codec version from 1.6 to 1.9. Contributed by Gary Gregory -* Update Ehcache version from 2.2.0 to 2.6.9. +* Update Ehcache version from 2.2.0 to 2.6.9. Contributed by Gary Gregory -* Update Ehcache version from 2.2.0 to 2.6.9. +* Update Ehcache version from 2.2.0 to 2.6.9. Contributed by Gary Gregory -* Update Spymemcached version from 2.6 to 2.11.4. +* Update Spymemcached version from 2.6 to 2.11.4. Contributed by Gary Gregory -* Update SLF4J version from 1.5.11 to 1.7.7. +* Update SLF4J version from 1.5.11 to 1.7.7. Contributed by Gary Gregory @@ -140,7 +142,7 @@ in 4.4 series are: * Enhanced redesigned and rewritten default SSL hostname verifier with improved RFC 2818 compliance -* Default SSL hostname verifier and default cookie policy now validate certificate identity +* Default SSL hostname verifier and default cookie policy now validate certificate identity and cookie domain of origin against the public suffix list maintained by Mozilla.org @@ -245,7 +247,7 @@ Changelog: * [HTTPCLIENT-1454] Make connection operator APIs public. Contributed by Tamas Cservenak -* Update JUnit to version 4.11 from 4.9 +* Update JUnit to version 4.11 from 4.9 Contributed by Gary Gregory @@ -253,9 +255,9 @@ Changelog: Release 4.3.4 ------------------- -HttpClient 4.3.4 (GA) is a maintenance release that improves performance in high concurrency -scenarios. This version replaces dynamic proxies with custom proxy classes and eliminates thread -contention in java.reflect.Proxy.newInstance() when leasing connections from the connection pool +HttpClient 4.3.4 (GA) is a maintenance release that improves performance in high concurrency +scenarios. This version replaces dynamic proxies with custom proxy classes and eliminates thread +contention in java.reflect.Proxy.newInstance() when leasing connections from the connection pool and processing response messages. @@ -272,7 +274,7 @@ Changelog: * [HTTPCLIENT-1474] Fixed broken entity enclosing requests in HC Fluent. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1470] CachingExec(ClientExecChain, HttpCache, CacheConfig, AsynchronousValidator) +* [HTTPCLIENT-1470] CachingExec(ClientExecChain, HttpCache, CacheConfig, AsynchronousValidator) throws NPE if config is null @@ -293,7 +295,7 @@ Changelog: Contributed by Oleg Kalnichevski * [HTTPCLIENT-1453] Thread safety regression in PoolingHttpClientConnectionManager - #closeExpiredConnections that can lead to ConcurrentModificationException. + #closeExpiredConnections that can lead to ConcurrentModificationException. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1461] fixed performance degradation in compressed content processing @@ -311,9 +313,9 @@ Changelog: Release 4.3.2 ------------------- -HttpClient 4.3.2 (GA) is a maintenance release that delivers a number of improvements -as well as bug fixes for issues reported since 4.3.1 release. SNI support for -Oracle JRE 1.7+ is being among the most notable improvements. +HttpClient 4.3.2 (GA) is a maintenance release that delivers a number of improvements +as well as bug fixes for issues reported since 4.3.1 release. SNI support for +Oracle JRE 1.7+ is being among the most notable improvements. Users of HttpClient 4.3 are encouraged to upgrade. @@ -322,7 +324,7 @@ Changelog: * [HTTPCLIENT-1447] Clients created with HttpClients.createMinimal do not work with absolute URIs Contributed by Joseph Walton - + * [HTTPCLIENT-1446] NTLM proxy + BASIC target auth fails with 'Unexpected state: MSG_TYPE3_GENERATED'. Contributed by Oleg Kalnichevski @@ -344,7 +346,7 @@ Changelog: Contributed by Oleg Kalnichevski * [HTTPCLIENT-1119] SNI support (Oracle Java 1.7+ only). - Contributed by Bruno Harbulot + Contributed by Bruno Harbulot * [HTTPCLIENT-1435] Fluent Executor ignores custom request properties. Contributed by Oleg Kalnichevski @@ -357,7 +359,7 @@ Changelog: a custom LayeredSchemeSocketFactory. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1425] Fixed socket closed exception thrown by caching HttpClient when the origin +* [HTTPCLIENT-1425] Fixed socket closed exception thrown by caching HttpClient when the origin server sends a long chunked response. Contributed by James Leigh @@ -373,8 +375,8 @@ Changelog: Release 4.3.1 ------------------- -HttpClient 4.3.1 (GA) is a bug fix release that addresses a number of issues reported since -release 4.3. +HttpClient 4.3.1 (GA) is a bug fix release that addresses a number of issues reported since +release 4.3. Users of HttpClient 4.3 are strongly encouraged to upgrade. @@ -392,7 +394,7 @@ Changelog Contributed by Oleg Kalnichevski * [HTTPCLIENT-1402] Cache default User-Agent value. - Contributed by yuexiaojun + Contributed by yuexiaojun * [HTTPCLIENT-1398] Fixed invalid OSGi metadata caused by corrupted Maven bundle plugin metadata. Contributed by Oleg Kalnichevski @@ -406,32 +408,32 @@ Changelog Release 4.3 Final ------------------- -This is the first stable (GA) release of HttpClient 4.3. The most notable enhancements included +This is the first stable (GA) release of HttpClient 4.3. The most notable enhancements included in this release are: * Support for Java 7 try-with-resources for resource management (connection release.) -* Added fluent Builder classes for HttpEntity, HttpRequest, HttpClient and SSLContext instances. +* Added fluent Builder classes for HttpEntity, HttpRequest, HttpClient and SSLContext instances. * Deprecation of preference and configuration API based on HttpParams interface in favor of constructor injection and plain configuration objects. -* Reliance on object immutability instead of access synchronization for thread safety. +* Reliance on object immutability instead of access synchronization for thread safety. Several old classes whose instances can be shared by multiple request exchanges have -been replaced by immutable equivalents. +been replaced by immutable equivalents. -* DefaultHttpClient, DecompressingHttpClient, CachingHttpClient and similar classes are -deprecated in favor of builder classes that produce immutable HttpClient instances. +* DefaultHttpClient, DecompressingHttpClient, CachingHttpClient and similar classes are +deprecated in favor of builder classes that produce immutable HttpClient instances. -* HttpClient builders now dynamically construct a request execution pipeline tailored +* HttpClient builders now dynamically construct a request execution pipeline tailored specifically to the user configuration by physically excluding unnecessary protocol components. -* There is now an option to construct a minimal HttpClient implementation that can only execute +* There is now an option to construct a minimal HttpClient implementation that can only execute basic HTTP message exchanges without redirects, authentication, state management or proxy support. -This feature might be of particular use in web crawler development. +This feature might be of particular use in web crawler development. -* There is now option to avoid strict URI syntax for request URIs by executing HTTP requests -with an explicitly specified target host. HttpClient will no longer attempt to parse the request +* There is now option to avoid strict URI syntax for request URIs by executing HTTP requests +with an explicitly specified target host. HttpClient will no longer attempt to parse the request URI if it does not need to extract the target host from it. This release also includes all fixes from the stable 4.2.x release branch. @@ -443,11 +445,11 @@ Changelog Contributed by James Leigh * [HTTPCLIENT-1394] Support for Native windows Negotiate/NTLM via JNA - Contributed by Ryan McKinley + Contributed by Ryan McKinley * [HTTPCLIENT-1384] Expose CacheInvalidator interface. Contributed by Nicolas Richeton - + * [HTTPCLIENT-1385] Fixed path normalization in CacheKeyGenerator Contributed by James Leigh @@ -458,8 +460,8 @@ Changelog * [HTTPCLIENT-1373] OPTIONS and TRACE should not invalidate cache Contributed by James Leigh -* [HTTPCLIENT-1383] HttpClient enters an infinite loop during NTLM authentication if the opposite - endpoint keeps responding with a type 2 NTLM response after type 3 MTLM message has already been +* [HTTPCLIENT-1383] HttpClient enters an infinite loop during NTLM authentication if the opposite + endpoint keeps responding with a type 2 NTLM response after type 3 MTLM message has already been sent by the client. Contributed by Oleg Kalnichevski @@ -467,7 +469,7 @@ Changelog are no longer constrained to ASCII values. Contributed by Karl Wright -* [HTTPCLIENT-1377] User principal for non-NTLM authentication is incorrectly generated when using +* [HTTPCLIENT-1377] User principal for non-NTLM authentication is incorrectly generated when using user credentials are specified as NTCredentials Contributed by Gary Gregory @@ -476,12 +478,12 @@ Changelog Release 4.3 BETA2 ------------------- -This is the second BETA release of HttpClient 4.3. The most notable features and improvements -in the 4.3 branch are: Support for Java 7 try-with-resources for resource management (connection -release); fluent Builder classes for HttpEntity, HttpRequest and HttpClient instances, deprecation -of preference and configuration API based on HttpParams interface in favor of constructor injection -and plain configuration objects, reliance on object immutability instead of access synchronization -for thread safety. +This is the second BETA release of HttpClient 4.3. The most notable features and improvements +in the 4.3 branch are: Support for Java 7 try-with-resources for resource management (connection +release); fluent Builder classes for HttpEntity, HttpRequest and HttpClient instances, deprecation +of preference and configuration API based on HttpParams interface in favor of constructor injection +and plain configuration objects, reliance on object immutability instead of access synchronization +for thread safety. This release also includes all fixes from the stable 4.2.x release branch. @@ -495,7 +497,7 @@ Changelog * [HTTPCLIENT-1365] NPE when ManagedHttpClientConnectionFactory.create(ConnectionConfig) is called with null. Contributed by Gary Gregory -* [HTTPCLIENT-1362] Better error messages for connect timed out and connection refused +* [HTTPCLIENT-1362] Better error messages for connect timed out and connection refused exceptions. Contributed by Oleg Kalnichevski @@ -511,17 +513,17 @@ Changelog * [HTTPCLIENT-1351] Added utility method to resolve final location from original request, target host and a list of redirects. - Contributed by James Leigh + Contributed by James Leigh -* [HTTPCLIENT-1344] Userinfo credentials in URI should not default to preemptive BASIC - authentication. +* [HTTPCLIENT-1344] Userinfo credentials in URI should not default to preemptive BASIC + authentication. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1345] Useinfo credentials ignored in redirect location header. +* [HTTPCLIENT-1345] Useinfo credentials ignored in redirect location header. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1294] HttpClient to rewrite host name of the redirect location URI in order - to avoid circular redirect exception due to host name case mismatch. +* [HTTPCLIENT-1294] HttpClient to rewrite host name of the redirect location URI in order + to avoid circular redirect exception due to host name case mismatch. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1264] Add support for multiple levels of browser compatibility @@ -529,26 +531,26 @@ Changelog argument for IE medium-security compatibility. Contributed by Karl Wright (kwright at apache.org) -* [HTTPCLIENT-1349] SSLSocketFactory incorrectly identifies key passed with keystore as +* [HTTPCLIENT-1349] SSLSocketFactory incorrectly identifies key passed with keystore as the keystore password. Contributed by David Graff * [HTTPCLIENT-1346] Ensure propagation of SSL handshake exceptions. Contributed by Pasi Eronen -* [HTTPCLIENT-1343] SSLSocketFactory optional parameters for supported SSL protocols and cipher - suites. +* [HTTPCLIENT-1343] SSLSocketFactory optional parameters for supported SSL protocols and cipher + suites. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1238] Contribute Bundle Activator And Central Proxy Configuration. - Contributed by Simone Tripodi + Contributed by Simone Tripodi -* [HTTPCLIENT-1299] (regression) cache incorrectly disposes of the underlying cache resource +* [HTTPCLIENT-1299] (regression) cache incorrectly disposes of the underlying cache resource when storing variant entry. - Contributed by James Leigh + Contributed by James Leigh * [HTTPCLIENT-1342] Redirects with underscore character in the location hostname cause - "java.lang.IllegalArgumentException: Host name may not be null". + "java.lang.IllegalArgumentException: Host name may not be null". Contributed by Oleg Kalnichevski @@ -557,10 +559,10 @@ Release 4.3 BETA1 ------------------- This is the first BETA release of HttpClient 4.3. The 4.3 branch enhances HttpClient in several -key areas and includes several notable features and improvements: Support for Java 7 -try-with-resources for resource management (connection release); fluent Builder classes for -HttpEntity, HttpRequest and HttpClient instances, deprecation of preference and configuration API -based on HttpParams interface in favor of constructor injection and plain configuration objects, +key areas and includes several notable features and improvements: Support for Java 7 +try-with-resources for resource management (connection release); fluent Builder classes for +HttpEntity, HttpRequest and HttpClient instances, deprecation of preference and configuration API +based on HttpParams interface in favor of constructor injection and plain configuration objects, reliance on object immutability instead of access synchronization for thread safety. This release also includes all fixes from the stable 4.2.x release branch. @@ -569,10 +571,10 @@ This release also includes all fixes from the stable 4.2.x release branch. Changelog ------------------- -* [HTTPCLIENT-1317] InetAddressUtils should handle IPv6 Addresses with Embedded IPv4 Addresses +* [HTTPCLIENT-1317] InetAddressUtils should handle IPv6 Addresses with Embedded IPv4 Addresses Contributed Sebastian Bazley . -* [HTTPCLIENT-1320] Leverage javax.net.ssl.SSLSocketFactory#getDefault() to initialize SSL context +* [HTTPCLIENT-1320] Leverage javax.net.ssl.SSLSocketFactory#getDefault() to initialize SSL context based on system defaults instead of using an internal custom routine. Contributed by Abe Backus and Oleg Kalnichevski @@ -580,7 +582,7 @@ Changelog Contributed Sebastian Bazley . * [HTTPCLIENT-1307] Future based asynchronous request execution. - Contributed by Jilles van Gurp + Contributed by Jilles van Gurp * [HTTPCLIENT-1313] Fixed IllegalStateException in deprecated ThreadSafeClientConnManager. Contributed by Oleg Kalnichevski @@ -594,14 +596,14 @@ Release 4.3 ALPHA1 ------------------- This is the first ALPHA release of HttpClient 4.3. The 4.3 branch enhances HttpClient in several -key areas and includes several notable features and improvements: Support for Java 7 -try-with-resources for resource management (connection release); fluent Builder classes for -HttpEntity, HttpRequest and HttpClient instances, deprecation of preference and configuration API -based on HttpParams interface in favor of constructor injection and plain configuration objects, -reliance on object immutability instead of access synchronization for thread safety. +key areas and includes several notable features and improvements: Support for Java 7 +try-with-resources for resource management (connection release); fluent Builder classes for +HttpEntity, HttpRequest and HttpClient instances, deprecation of preference and configuration API +based on HttpParams interface in favor of constructor injection and plain configuration objects, +reliance on object immutability instead of access synchronization for thread safety. -We are kindly asking all upstream projects to review API changes and help us improve -the APIs by providing feedback and sharing ideas on dev@hc.apache.org. +We are kindly asking all upstream projects to review API changes and help us improve +the APIs by providing feedback and sharing ideas on dev@hc.apache.org. This release also includes all fixes from the stable 4.2.x release branch. @@ -612,24 +614,24 @@ their API may change in the future 4.3 alpha and beta releases. Changelog ------------------- -* [HTTPCLIENT-1250] Allow query string to be ignored when determining cacheability for +* [HTTPCLIENT-1250] Allow query string to be ignored when determining cacheability for HTTP 1.0 responses. - Contributed by Don Brown + Contributed by Don Brown * [HTTPCLIENT-1261] Make SystemDefaultHttpClient honor http.agent system property. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-900] Don't enforce URI syntax for messages with an explicit target host. +* [HTTPCLIENT-900] Don't enforce URI syntax for messages with an explicit target host. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1190] HttpClient cache does not support "Vary: Cookie" Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1259] Calling #abort() on requests executed with DecompressingHttpClient has no +* [HTTPCLIENT-1259] Calling #abort() on requests executed with DecompressingHttpClient has no effect. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1253] URIBuilder setParameter() method could exceed the HTTP header size. +* [HTTPCLIENT-1253] URIBuilder setParameter() method could exceed the HTTP header size. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1216] Added method to force clean thread-local used by DateUtils. @@ -639,9 +641,9 @@ Changelog Release 4.2.3 ------------------- -HttpClient 4.2.3 (GA) is a bug fix release that addresses a number of issues reported since -release 4.2.2. This release also includes a thoroughly reworked NTLM authentication engine -which should result in a better compatibility with the newest Microsoft products. +HttpClient 4.2.3 (GA) is a bug fix release that addresses a number of issues reported since +release 4.2.2. This release also includes a thoroughly reworked NTLM authentication engine +which should result in a better compatibility with the newest Microsoft products. Users of HttpClient 4.x are advised to upgrade. @@ -652,70 +654,70 @@ Changelog that has a -1 value for the port. Contributed by Karl Wright -* [HTTPCLIENT-1290] 304 cached response never reused with If-modified-since conditional - requests. +* [HTTPCLIENT-1290] 304 cached response never reused with If-modified-since conditional + requests. Contributed by Francois-Xavier Bonnet -* [HTTPCLIENT-1291] Absolute request URIs without an explicitly specified path are rewritten - to have "/" path). +* [HTTPCLIENT-1291] Absolute request URIs without an explicitly specified path are rewritten + to have "/" path). Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1286] Request URI rewriting is inconsistent - URI fragments are not removed - from absolute request URIs. +* [HTTPCLIENT-1286] Request URI rewriting is inconsistent - URI fragments are not removed + from absolute request URIs. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1284] HttpClient incorrectly generates Host header when physical connection - route differs from the host name specified in the request URI. + route differs from the host name specified in the request URI. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1293] Kerberos and SPNego auth schemes use incorrect authorization header name +* [HTTPCLIENT-1293] Kerberos and SPNego auth schemes use incorrect authorization header name when authenticating with a proxy. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1283] NTLM needs to use Locale-independent form of toUpperCase(). - Contributed by Karl Wright + Contributed by Karl Wright -* [HTTPCLIENT-1279] Target host responding with status 407 (proxy authentication required) - causes an NPE. +* [HTTPCLIENT-1279] Target host responding with status 407 (proxy authentication required) + causes an NPE. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1281] GzipDecompressingEntity does not release InputStream when an IOException - occurs while reading the Gzip header - Contributed by Francois-Xavier Bonnet +* [HTTPCLIENT-1281] GzipDecompressingEntity does not release InputStream when an IOException + occurs while reading the Gzip header + Contributed by Francois-Xavier Bonnet * [HTTPCLIENT-1277] Caching client sends a 304 to an unconditional request. Contributed by Francois-Xavier Bonnet * [HTTPCLIENT-1278] Update NTLM documentation. - Contributed by Karl Wright + Contributed by Karl Wright * SystemDefaultHttpClient misinterprets 'http.keepAlive' default value and disables connection persistence if the system property is not set. This causes connection based authentication schemes such as NTLM to fail. -* [HTTPCLIENT-1276] cache update on a 304 response causes NPE. - Contributed by Francois-Xavier Bonnet +* [HTTPCLIENT-1276] cache update on a 304 response causes NPE. + Contributed by Francois-Xavier Bonnet -* [HTTPCLIENT-1273] DecompressingHttpClient does not automatically consume response - content in case of an i/o, HTTP or runtime exception thrown by the decompressing - protocol interceptor leading to a potential connection leak. +* [HTTPCLIENT-1273] DecompressingHttpClient does not automatically consume response + content in case of an i/o, HTTP or runtime exception thrown by the decompressing + protocol interceptor leading to a potential connection leak. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1268] NTLM engine refactor fix, to correct a buffer overrun, and get NTLMv2 flags right. - Contributed by Karl Wright + Contributed by Karl Wright * [HTTPCLIENT-1266] NTLM engine refactoring and compatibility improvements. - Contributed by Karl Wright + Contributed by Karl Wright -* [HTTPCLIENT-1263] BrowserCompatSpec: attribute values containing spaces or special characters +* [HTTPCLIENT-1263] BrowserCompatSpec: attribute values containing spaces or special characters should be enclosed with quotes marks for version 1 cookies. - Contributed by Francois-Xavier Bonnet + Contributed by Francois-Xavier Bonnet * [HTTPCLIENT-1263] CachingHttpClient fails to release connections back to the connection - manager for some type of HTTP response messages when used together with DecompressingHttpClient. - Contributed by Francois-Xavier Bonnet + manager for some type of HTTP response messages when used together with DecompressingHttpClient. + Contributed by Francois-Xavier Bonnet * [HTTPCLIENT-1258] Fixed NullPointerException in NTLMEngineImpl caused by null NT domain attribute. @@ -729,10 +731,10 @@ Changelog -Release 4.2.2 +Release 4.2.2 ------------------- -HttpClient 4.2.2 (GA) is a bug fix release that addresses a number of issues reported since +HttpClient 4.2.2 (GA) is a bug fix release that addresses a number of issues reported since release 4.2.1. Users of HttpClient 4.2 are advised to upgrade. @@ -741,25 +743,25 @@ Changelog ------------------- * [HTTPCLIENT-1248] Default and lax redirect strategies should not convert requests redirected - with 307 status to GET method. + with 307 status to GET method. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1215] BasicAuthCache does not take default ports into consideration when looking up cached authentication details by HttpHost key. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1241] (regression) Preemptive BASIC authentication failure should be considered - final and no further attempts to re-authenticate using the same credentials should be made. +* [HTTPCLIENT-1241] (regression) Preemptive BASIC authentication failure should be considered + final and no further attempts to re-authenticate using the same credentials should be made. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1229] Fixed NPE in BasicClientConnectionManager that can be triggered by releasing - connection after the connection manager has already been shut down. + connection after the connection manager has already been shut down. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1227] Date parsing in DateUtils made more efficient. Contributed by Patrick Linskey -* [HTTPCLIENT-1224] (regression) NTLM auth not retried after a redirect over a non-persistent +* [HTTPCLIENT-1224] (regression) NTLM auth not retried after a redirect over a non-persistent connection. Contributed by Oleg Kalnichevski @@ -767,16 +769,16 @@ Changelog from Content-Location. Contributed by Jon Moore . Contributed by Jon Moore -* [HTTPCLIENT-1217] AutoRetryHttpClient does not release connection used by the previous response +* [HTTPCLIENT-1217] AutoRetryHttpClient does not release connection used by the previous response when request is retried Contributed by Oleg Kalnichevski -Release 4.2.1 +Release 4.2.1 ------------------- -HttpClient 4.2.1 (GA) is a bug fix release that addresses a number of issues reported since +HttpClient 4.2.1 (GA) is a bug fix release that addresses a number of issues reported since release 4.2. Users of HttpClient 4.2 are advised to upgrade. @@ -798,7 +800,7 @@ Changelog Contributed by Jon Moore * [HTTPCLIENT-1200] DecompressingHttpClient fails to generate correct HttpHost context attribute. - Contributed by Guillaume Castagnino + Contributed by Guillaume Castagnino * [HTTPCLIENT-1192] URIBuilder encodes query parameters twice. Contributed by Oleg Kalnichevski and Sebastian Bazley . @@ -806,14 +808,14 @@ Changelog * [HTTPCLIENT-1196] Fixed NPE in UrlEncodedFormEntity constructor thrown if charset is null. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1193] Fixed regression in the route tracking logic of the default connection manager +* [HTTPCLIENT-1193] Fixed regression in the route tracking logic of the default connection manager causing cross-site redirect failures. Contributed by Oleg Kalnichevski Release 4.2 ------------------- -This is the first stable (GA) release of HttpClient 4.2. The most notable enhancements included +This is the first stable (GA) release of HttpClient 4.2. The most notable enhancements included in this release are: * New facade API for HttpClient based on the concept of a fluent interface. The fluent API exposes @@ -821,7 +823,7 @@ in this release are: that do not require the full flexibility of HttpClient. However, the fluent API almost fully relieves the users from having to deal with connection management and resource deallocation. -* Redesigned and rewritten connection management code. +* Redesigned and rewritten connection management code. * Enhanced HTTP authentication API that enables HttpClient to handle more complex authentication scenarios. HttpClient 4.2 is now capable of making use of multiple authentication challenges @@ -833,14 +835,14 @@ in this release are: Changelog ------------------- -* [HTTPCLIENT-1187] If a revalidation response is deemed too old CachingHttpClient fails to +* [HTTPCLIENT-1187] If a revalidation response is deemed too old CachingHttpClient fails to consume its content resulting in a connection leak. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1186] State of newly created connections in the connection pool is not always - correctly updated potentially allowing those connections to be leased to users with a different - security context. - Contributed by Ralf Poehlmann +* [HTTPCLIENT-1186] State of newly created connections in the connection pool is not always + correctly updated potentially allowing those connections to be leased to users with a different + security context. + Contributed by Ralf Poehlmann * [HTTPCLIENT-1179] Upgraded Commons Codec dependency to version 1.6 Contributed by Oleg Kalnichevski @@ -904,23 +906,23 @@ Changelog * [HTTPCLIENT-1154] MemcachedHttpCacheStorage should allow client to specify custom prefix string for keys. Contributed by Jon Moore . - + * [HTTPCLIENT-1153] MemcachedHttpCacheStorage uses URL as cache key; shouldn't due to fixed maximum-length memcached keys. Contributed by Jon Moore . - + * [HTTPCLIENT-1157] MemcachedHttpCacheStroage should throw IOExceptions instead of RuntimeExceptions. Contributed by James Miller . - + * [HTTPCLIENT-1152] MemcachedHttpCacheStorage should verify class of returned object before casting. Contributed by Rajika Kumarasiri . -* [HTTPCLIENT-1155] CachingHttpClient fails to ensure that the response content gets fully consumed +* [HTTPCLIENT-1155] CachingHttpClient fails to ensure that the response content gets fully consumed when using a ResponseHandler, which can potentially lead to connection leaks. Contributed by James Miller - + * [HTTPCLIENT-1147] When HttpClient-Cache cannot open cache file, should act like miss. Contributed by Joe Campbell @@ -929,7 +931,7 @@ Changelog * [HTTPCLIENT-1142] Infinite loop on NTLM authentication failure. Contributed by Oleg Kalnichevski - + * [HTTPCLIENT-1143] CachingHttpClient leaks connections with stale-if-error. Contributed by James Miller @@ -1027,20 +1029,20 @@ Changelog Release 4.1.2 ------------------- -The HttpClient 4.1.2 is a bug fix release that addresses a number of non-critical issues reported +The HttpClient 4.1.2 is a bug fix release that addresses a number of non-critical issues reported since release 4.1.1. * [HTTPCLIENT-1100] Missing Content-Length header makes cached entry invalid Contributed by Bart Robeyns -* [HTTPCLIENT-1098] Avoid expensive reverse DNS lookup on connect timeout exception. +* [HTTPCLIENT-1098] Avoid expensive reverse DNS lookup on connect timeout exception. Contributed by Thomas Boettcher -* [HTTPCLIENT-1097] BrowserCompatHostnameVerifier and StrictHostnameVerifier should handle +* [HTTPCLIENT-1097] BrowserCompatHostnameVerifier and StrictHostnameVerifier should handle wildcards in SSL certificates better. Contributed by Sebastian Bazley -* [HTTPCLIENT-1092] If ClientPNames.VIRTUAL_HOST does not provide the port, derive it from the +* [HTTPCLIENT-1092] If ClientPNames.VIRTUAL_HOST does not provide the port, derive it from the current request. Contributed by Sebastian Bazley @@ -1049,15 +1051,15 @@ since release 4.1.1. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1079] Fixed Kerberos cross-realm support - Contributed by Michael Osipov <1983-01-06 at gmx.net> + Contributed by Michael Osipov <1983-01-06 at gmx.net> -* [HTTPCLIENT-1078] Decompressing entities (DeflateDecompressingEntity, GzipDecompressingEntity) +* [HTTPCLIENT-1078] Decompressing entities (DeflateDecompressingEntity, GzipDecompressingEntity) do not close content stream in #writeTo() method. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1075] Decompressing entities (DeflateDecompressingEntity, GzipDecompressingEntity) +* [HTTPCLIENT-1075] Decompressing entities (DeflateDecompressingEntity, GzipDecompressingEntity) do not correctly handle content streaming. - Contributed by James Abley + Contributed by James Abley * [HTTPCLIENT-1051] Avoid reverse DNS lookups when opening SSL connections by IP address. Contributed by Oleg Kalnichevski @@ -1066,18 +1068,18 @@ since release 4.1.1. Release 4.1.1 ------------------- -HttpClient v4.1.1 is a bug fix release that addresses a number of issues reported since -release 4.1, including one critical security issue (HTTPCLIENT-1061). All users of HttpClient 4.0.x +HttpClient v4.1.1 is a bug fix release that addresses a number of issues reported since +release 4.1, including one critical security issue (HTTPCLIENT-1061). All users of HttpClient 4.0.x and 4.1 are strongly encouraged to upgrade. -* [HTTPCLIENT-1069] HttpHostConnectException not correctly retried for direct and non-tunnelled - proxy connections. +* [HTTPCLIENT-1069] HttpHostConnectException not correctly retried for direct and non-tunnelled + proxy connections. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1066] Changed the way URIUtils#rewriteURI handles multiple consecutive slashes in the URI path component: multiple leading slashes will be replaced by one slash in order to avoid - confusion with the authority component. The remaining content of the path will not be modified. - (also see HTTPCLIENT-929). + confusion with the authority component. The remaining content of the path will not be modified. + (also see HTTPCLIENT-929). Contributed by Oleg Kalnichevski * [HTTPCLIENT-1061] Fixed critical bug causing Proxy-Authorization header to be sent to the target @@ -1085,10 +1087,10 @@ and 4.1 are strongly encouraged to upgrade. Contributed by Oleg Kalnichevski * [HTTPCLIENT-1056] Fixed bug causing the RequestAuthCache protocol interceptor to generate - an invalid AuthScope instance when looking up user credentials for preemptive authentication. + an invalid AuthScope instance when looking up user credentials for preemptive authentication. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1053] Fixed the way DigestScheme generates nonce-count values. +* [HTTPCLIENT-1053] Fixed the way DigestScheme generates nonce-count values. Contributed by Oleg Kalnichevski @@ -1101,7 +1103,7 @@ functional improvements and popular features. * Response caching conditionally compliant with HTTP/1.1 specification (full compliance with MUST requirements, partial compliance with SHOULD requirements) -* Full support for NTLMv1, NTLMv2, and NTLM2 Session authentication. The NTLM protocol code +* Full support for NTLMv1, NTLMv2, and NTLM2 Session authentication. The NTLM protocol code was kindly contributed by the Lucene Connector Framework project. * Support for SPNEGO/Kerberos authentication. @@ -1109,12 +1111,12 @@ functional improvements and popular features. * Persistence of authentication data between request executions within the same execution context. * Support for preemptive authentication for BASIC and DIGEST schemes. - -* Support for transparent content encoding. Please note transparent content encoding is not - enabled per default in order to avoid conflicts with already existing custom content encoding + +* Support for transparent content encoding. Please note transparent content encoding is not + enabled per default in order to avoid conflicts with already existing custom content encoding solutions. -* Mechanism to bypass the standard certificate trust verification (useful when dealing with +* Mechanism to bypass the standard certificate trust verification (useful when dealing with self-signed certificates). * Simplified configuration for connection managers. @@ -1127,7 +1129,7 @@ maintained and supported by the Apache HttpComponents project. Changelog ------------------- * The public API for the caching module had a minor change between 4.1-beta and 4.1-GA to the - HttpCacheEntry class - the deprecated public Set getVariantURIs() method and constructor + HttpCacheEntry class - the deprecated public Set getVariantURIs() method and constructor public HttpCacheEntry(Date requestDate, Date responseDate, StatusLine statusLine, Header[] responseHeaders, Resource resource, Set variants) @@ -1136,11 +1138,11 @@ Changelog * Changed Browser-Compatibility and Best-Match cookie policies to emulate the behaviour of FireFox more closely when parsing Netscape style cookies. Comma will no longer be treated as a header - element separator if Set-Cookie does not contain a Version attribute mandated by the + element separator if Set-Cookie does not contain a Version attribute mandated by the RFC2109 / RFC 2965 cookie specifications. Contributed by Oleg Kalnichevski -* [HTTPCLIENT-1036] StringBody has incorrect default for characterset. (Default changed +* [HTTPCLIENT-1036] StringBody has incorrect default for characterset. (Default changed to US-ASCII) Contributed by Sebastian Bazley @@ -1149,7 +1151,7 @@ Changelog Michajlo Matijkiw , and Matthew Hawthorne . -* [HTTPCLIENT-1033] HttpRoute.equals(Object o) is quite inefficient, as it does not take full +* [HTTPCLIENT-1033] HttpRoute.equals(Object o) is quite inefficient, as it does not take full advantage of shortcut logic. Contributed by Sebastian Bazley @@ -1160,8 +1162,8 @@ Release 4.1 BETA1 ------------------- HttpClient 4.1 BETA1 finalizes the 4.1 API and brings a number of major improvements to the HTTP -caching module. This release also adds full support for NTLMv1, NTLMv2, and NTLM2 Session -authentication. The NTLM protocol code was kindly contributed by the Lucene Connector Framework +caching module. This release also adds full support for NTLMv1, NTLMv2, and NTLM2 Session +authentication. The NTLM protocol code was kindly contributed by the Lucene Connector Framework project. Changelog @@ -1176,14 +1178,14 @@ Changelog Contributed by Karl Wright * [HTTPCLIENT-1008] Send all variants' ETags on "variant miss". - Contributed by Michajlo Matijkiw and + Contributed by Michajlo Matijkiw and Mohammed Azeem Uddin * [HTTPCLIENT-1011] Handling of IOExceptions thrown by cache components. Contributed by Jonathan Moore * [HTTPCLIENT-1003] Handle conditional requests in cache. - Contributed by Michajlo Matijkiw and + Contributed by Michajlo Matijkiw and Mohammed Azeem Uddin * [HTTPCLIENT-1002] Stale connection check fails if wire logging is on. @@ -1197,28 +1199,28 @@ Changelog Contributed by Oleg Kalnichevski * [HTTPCLIENT-998] Cache should use both Last-Modified and ETag for validations when available. - Contributed by Jonathan Moore + Contributed by Jonathan Moore -* [HTTPCLIENT-997] Cache module should handle out-of-order validations properly and unconditionally +* [HTTPCLIENT-997] Cache module should handle out-of-order validations properly and unconditionally refresh. - Contributed by Jonathan Moore + Contributed by Jonathan Moore -* [HTTPCLIENT-994] Cache does not allow client to override origin-specified freshness using +* [HTTPCLIENT-994] Cache does not allow client to override origin-specified freshness using max-stale. Contributed by Jonathan Moore -* [HTTPCLIENT-995] Cache returns cached responses even if validators not consistent with all +* [HTTPCLIENT-995] Cache returns cached responses even if validators not consistent with all conditional headers. Contributed by Jonathan Moore * [HTTPCLIENT-977] Memcached implementation for HttpCache. Contributed by Mohammed Azeem Uddin -* [HTTPCLIENT-992] cache should not generate stale responses to requests explicitly requesting +* [HTTPCLIENT-992] cache should not generate stale responses to requests explicitly requesting first-hand or fresh ones. Contributed by Jonathan Moore -* [HTTPCLIENT-991] cache module produces improperly formatted Warning header when revalidation +* [HTTPCLIENT-991] cache module produces improperly formatted Warning header when revalidation fails. Contributed by Jonathan Moore @@ -1238,18 +1240,18 @@ Changelog * [HTTPCLIENT-985] cache module should populate Via header to capture upstream and downstream protocols Contributed by Jonathan Moore -* [HTTPCLIENT-984] Additional conditional compliance tests for the caching module for +* [HTTPCLIENT-984] Additional conditional compliance tests for the caching module for Content-Encoding, Content-Location, Date, Expires, Server, Transfer-Encoding, and Vary headers. Contributed by Jonathan Moore * [HTTPCLIENT-978] HTTP cache update exception handling Contributed by Michajlo Matijkiw -* [HTTPCLIENT-981] CachingHttpClient returns a 411 respones when executing a POST (HttpPost) +* [HTTPCLIENT-981] CachingHttpClient returns a 411 respones when executing a POST (HttpPost) request. Contributed by Joe Campbell -* [HTTPCLIENT-980] CachingHttpClient returns a 503 response when the backend HttpClient produces +* [HTTPCLIENT-980] CachingHttpClient returns a 503 response when the backend HttpClient produces an IOException. Contributed by Jonathan Moore @@ -1258,7 +1260,7 @@ Changelog * [HTTPCLIENT-967] support for non-shared (private) caches Contributed by Jonathan Moore - + * [HTTPCLIENT-969] BasicCookieStore#getCookies() to return a copy of Cookie list Contributed by David Smiley From 4ab8948dc527569aa9cac31f3deec9f3e1ba8f71 Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Sat, 30 May 2015 19:45:10 +0000 Subject: [PATCH 007/204] Unintentionally removed empty lines git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682648 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index e0fdcfc8ae..fb7c288052 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -29,6 +29,7 @@ Changelog: Contributed by Michael Osipov + Release 4.4.1 ------------------- From eb4a62f60993db199f05932cfbc3f62034abb514 Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Sat, 30 May 2015 20:11:17 +0000 Subject: [PATCH 008/204] HTTPCLIENT-1654: Deprecate/remove RequestConfig#decompressionEnabled in favor of #contentCompressionEnabled git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682650 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/client/config/RequestConfig.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java index 08c27a1b77..459a0c7a41 100644 --- a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java +++ b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java @@ -315,7 +315,9 @@ public int getSocketTimeout() { *

* * @since 4.4 + * @deprecated (4.5) Use {@link #isContentCompressionEnabled()} */ + @Deprecated public boolean isDecompressionEnabled() { return decompressionEnabled; } @@ -501,6 +503,11 @@ public Builder setSocketTimeout(final int socketTimeout) { return this; } + /** + * @deprecated (4.5) Set {@link #setContentCompressionEnabled(boolean)} to {@code false} and + * add the {@code Accept-Encoding} request header. + */ + @Deprecated public Builder setDecompressionEnabled(final boolean decompressionEnabled) { this.decompressionEnabled = decompressionEnabled; return this; From 2227d18696aa5a9ce3cb341ddbf8c5a5f735dc66 Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Sat, 30 May 2015 20:27:58 +0000 Subject: [PATCH 009/204] Added HTTPCLIENT-1654 to release notes git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682652 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index fb7c288052..5cabfbaa6d 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -28,6 +28,9 @@ Changelog: * [HTTPCLIENT-1651]: Add ability to disable content compression on a request basis Contributed by Michael Osipov +* [HTTPCLIENT-1654]: Deprecate/remove RequestConfig#decompressionEnabled in favor of #contentCompressionEnabled + Contributed by Michael Osipov + Release 4.4.1 From ea21ed26a76177bbf7ee4274de640ab579e13850 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 31 May 2015 10:46:03 +0000 Subject: [PATCH 010/204] HTTPCLIENT-1654: better backward compatibility git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1682713 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/client/config/RequestConfig.java | 13 +++---------- .../client/protocol/ResponseContentEncoding.java | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java index 459a0c7a41..87f772ff61 100644 --- a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java +++ b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java @@ -58,14 +58,13 @@ public class RequestConfig implements Cloneable { private final int connectionRequestTimeout; private final int connectTimeout; private final int socketTimeout; - private final boolean decompressionEnabled; private final boolean contentCompressionEnabled; /** * Intended for CDI compatibility */ protected RequestConfig() { - this(false, null, null, false, null, false, false, false, 0, false, null, null, 0, 0, 0, false, false); + this(false, null, null, false, null, false, false, false, 0, false, null, null, 0, 0, 0, true); } RequestConfig( @@ -84,7 +83,6 @@ protected RequestConfig() { final int connectionRequestTimeout, final int connectTimeout, final int socketTimeout, - final boolean decompressionEnabled, final boolean contentCompressionEnabled) { super(); this.expectContinueEnabled = expectContinueEnabled; @@ -102,7 +100,6 @@ protected RequestConfig() { this.connectionRequestTimeout = connectionRequestTimeout; this.connectTimeout = connectTimeout; this.socketTimeout = socketTimeout; - this.decompressionEnabled = decompressionEnabled; this.contentCompressionEnabled = contentCompressionEnabled; } @@ -319,7 +316,7 @@ public int getSocketTimeout() { */ @Deprecated public boolean isDecompressionEnabled() { - return decompressionEnabled; + return contentCompressionEnabled; } /** @@ -357,7 +354,6 @@ public String toString() { builder.append(", connectionRequestTimeout=").append(connectionRequestTimeout); builder.append(", connectTimeout=").append(connectTimeout); builder.append(", socketTimeout=").append(socketTimeout); - builder.append(", decompressionEnabled=").append(decompressionEnabled); builder.append(", contentCompressionEnabled=").append(contentCompressionEnabled); builder.append("]"); return builder.toString(); @@ -406,7 +402,6 @@ public static class Builder { private int connectionRequestTimeout; private int connectTimeout; private int socketTimeout; - private boolean decompressionEnabled; private boolean contentCompressionEnabled; Builder() { @@ -419,7 +414,6 @@ public static class Builder { this.connectionRequestTimeout = -1; this.connectTimeout = -1; this.socketTimeout = -1; - this.decompressionEnabled = true; this.contentCompressionEnabled = true; } @@ -509,7 +503,7 @@ public Builder setSocketTimeout(final int socketTimeout) { */ @Deprecated public Builder setDecompressionEnabled(final boolean decompressionEnabled) { - this.decompressionEnabled = decompressionEnabled; + this.contentCompressionEnabled = decompressionEnabled; return this; } @@ -535,7 +529,6 @@ public RequestConfig build() { connectionRequestTimeout, connectTimeout, socketTimeout, - decompressionEnabled, contentCompressionEnabled); } diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java index 9cb4adbbec..c4d0cfc9fe 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java @@ -129,7 +129,7 @@ public void process( final RequestConfig requestConfig = clientContext.getRequestConfig(); // entity can be null in case of 304 Not Modified, 204 No Content or similar // check for zero length entity. - if (requestConfig.isDecompressionEnabled() && entity != null && entity.getContentLength() != 0) { + if (requestConfig.isContentCompressionEnabled() && entity != null && entity.getContentLength() != 0) { final Header ceheader = entity.getContentEncoding(); if (ceheader != null) { final HeaderElement[] codecs = ceheader.getElements(); From 20e3f42df25aad30df097aa12d8b52ad10eeb3bc Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 4 Jun 2015 07:38:42 +0000 Subject: [PATCH 011/204] Cache request line in HttpRequestWrapper Contributed by Dmitry Potapov git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1683475 13f79535-47bb-0310-9956-ffa450edef68 --- .../client/methods/HttpRequestWrapper.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java index a593cecc73..3df8bbb5b6 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java @@ -56,6 +56,7 @@ public class HttpRequestWrapper extends AbstractHttpMessage implements HttpUriRe private final HttpRequest original; private final HttpHost target; private final String method; + private RequestLine requestLine; private ProtocolVersion version; private URI uri; @@ -80,6 +81,7 @@ public ProtocolVersion getProtocolVersion() { public void setProtocolVersion(final ProtocolVersion version) { this.version = version; + this.requestLine = null; } @Override @@ -89,6 +91,7 @@ public URI getURI() { public void setURI(final URI uri) { this.uri = uri; + this.requestLine = null; } @Override @@ -108,16 +111,19 @@ public boolean isAborted() { @Override public RequestLine getRequestLine() { - String requestUri = null; - if (this.uri != null) { - requestUri = this.uri.toASCIIString(); - } else { - requestUri = this.original.getRequestLine().getUri(); - } - if (requestUri == null || requestUri.isEmpty()) { - requestUri = "/"; + if (this.requestLine == null) { + String requestUri; + if (this.uri != null) { + requestUri = this.uri.toASCIIString(); + } else { + requestUri = this.original.getRequestLine().getUri(); + } + if (requestUri == null || requestUri.isEmpty()) { + requestUri = "/"; + } + this.requestLine = new BasicRequestLine(this.method, requestUri, getProtocolVersion()); } - return new BasicRequestLine(this.method, requestUri, getProtocolVersion()); + return this.requestLine; } public HttpRequest getOriginal() { From 12482402c405cf0ed38ea4d29f00a6ec9cbb2ea7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 4 Jun 2015 08:41:39 +0000 Subject: [PATCH 012/204] Upgraded HttpClient version to 4.5.1-SNAPSHOT git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1683489 13f79535-47bb-0310-9956-ffa450edef68 --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 8 ++++---- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index bfb2714325..e2b351628d 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5-alpha1-SNAPSHOT + 4.5.1-SNAPSHOT fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index dac5d39355..d2a84ff5e9 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5-alpha1-SNAPSHOT + 4.5.1-SNAPSHOT httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 1a01dea8fc..dfd1402a50 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5-alpha1-SNAPSHOT + 4.5.1-SNAPSHOT httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index 71dbda60e0..e7208bdaa8 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5-alpha1-SNAPSHOT + 4.5.1-SNAPSHOT httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 7b12c31867..117a838332 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5-alpha1-SNAPSHOT + 4.5.1-SNAPSHOT httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index dbedf8d825..3a0618fe2d 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5-alpha1-SNAPSHOT + 4.5.1-SNAPSHOT httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 0a02cfc3fa..815cce92c7 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5-alpha1-SNAPSHOT + 4.5.1-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client 1999 @@ -58,9 +58,9 @@ - scm:svn:https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk - scm:svn:https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk - https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk + scm:svn:https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x + scm:svn:https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x + https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x From 78cf770aec88b6bfad9dfbdc12d8b92df2d84616 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 5 Jun 2015 09:17:41 +0000 Subject: [PATCH 013/204] HTTPCLIENT-1655: HttpClient sends RST instead of FIN ACK sequence when using non-persistant connections git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1683684 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/conn/ConnectionReleaseTrigger.java | 3 +- .../http/impl/execchain/ConnectionHolder.java | 73 ++++++++++--------- .../impl/execchain/HttpResponseProxy.java | 2 +- .../impl/execchain/ResponseEntityProxy.java | 34 +++++++-- .../impl/execchain/TestMainClientExec.java | 2 +- .../impl/execchain/TestMinimalClientExec.java | 2 +- .../execchain/TestResponseEntityWrapper.java | 2 +- 7 files changed, 68 insertions(+), 50 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ConnectionReleaseTrigger.java b/httpclient/src/main/java/org/apache/http/conn/ConnectionReleaseTrigger.java index 1317c227d1..8a47637228 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ConnectionReleaseTrigger.java +++ b/httpclient/src/main/java/org/apache/http/conn/ConnectionReleaseTrigger.java @@ -31,8 +31,7 @@ /** * Interface for releasing a connection. This can be implemented by various * "trigger" objects which are associated with a connection, for example - * a {@link EofSensorInputStream stream} or an {@link BasicManagedEntity entity} - * or the {@link ManagedClientConnection connection} itself. + * a {@link EofSensorInputStream} or the {@link ManagedHttpClientConnection} itself. *

* The methods in this interface can safely be called multiple times. * The first invocation releases the connection, subsequent calls diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java index 1ebf02daea..0f6e4f3e85 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java @@ -30,6 +30,7 @@ import java.io.Closeable; import java.io.IOException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.logging.Log; import org.apache.http.HttpClientConnection; @@ -50,13 +51,12 @@ class ConnectionHolder implements ConnectionReleaseTrigger, Cancellable, Closeab private final HttpClientConnectionManager manager; private final HttpClientConnection managedConn; + private final AtomicBoolean released; private volatile boolean reusable; private volatile Object state; private volatile long validDuration; private volatile TimeUnit tunit; - private volatile boolean released; - public ConnectionHolder( final Log log, final HttpClientConnectionManager manager, @@ -65,6 +65,7 @@ public ConnectionHolder( this.log = log; this.manager = manager; this.managedConn = managedConn; + this.released = new AtomicBoolean(false); } public boolean isReusable() { @@ -90,19 +91,40 @@ public void setValidFor(final long duration, final TimeUnit tunit) { } } + private void releaseConnection(final boolean reusable) { + if (this.released.compareAndSet(false, true)) { + synchronized (this.managedConn) { + if (reusable) { + this.manager.releaseConnection(this.managedConn, + this.state, this.validDuration, this.tunit); + } else { + try { + this.managedConn.close(); + log.debug("Connection discarded"); + } catch (final IOException ex) { + if (this.log.isDebugEnabled()) { + this.log.debug(ex.getMessage(), ex); + } + } finally { + this.manager.releaseConnection( + this.managedConn, null, 0, TimeUnit.MILLISECONDS); + } + } + } + } + } + @Override public void releaseConnection() { - synchronized (this.managedConn) { - if (this.released) { - return; - } - this.released = true; - if (this.reusable) { - this.manager.releaseConnection(this.managedConn, - this.state, this.validDuration, this.tunit); - } else { + releaseConnection(this.reusable); + } + + @Override + public void abortConnection() { + if (this.released.compareAndSet(false, true)) { + synchronized (this.managedConn) { try { - this.managedConn.close(); + this.managedConn.shutdown(); log.debug("Connection discarded"); } catch (final IOException ex) { if (this.log.isDebugEnabled()) { @@ -116,42 +138,21 @@ public void releaseConnection() { } } - @Override - public void abortConnection() { - synchronized (this.managedConn) { - if (this.released) { - return; - } - this.released = true; - try { - this.managedConn.shutdown(); - log.debug("Connection discarded"); - } catch (final IOException ex) { - if (this.log.isDebugEnabled()) { - this.log.debug(ex.getMessage(), ex); - } - } finally { - this.manager.releaseConnection( - this.managedConn, null, 0, TimeUnit.MILLISECONDS); - } - } - } - @Override public boolean cancel() { - final boolean alreadyReleased = this.released; + final boolean alreadyReleased = this.released.get(); log.debug("Cancelling request execution"); abortConnection(); return !alreadyReleased; } public boolean isReleased() { - return this.released; + return this.released.get(); } @Override public void close() throws IOException { - abortConnection(); + releaseConnection(false); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java index 4a6ca05b70..0184ec2500 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java @@ -61,7 +61,7 @@ public HttpResponseProxy(final HttpResponse original, final ConnectionHolder con @Override public void close() throws IOException { if (this.connHolder != null) { - this.connHolder.abortConnection(); + this.connHolder.close(); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java index 9f66de65cd..7f2c42d35f 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java @@ -61,7 +61,13 @@ public static void enchance(final HttpResponse response, final ConnectionHolder this.connHolder = connHolder; } - private void cleanup() { + private void cleanup() throws IOException { + if (this.connHolder != null) { + this.connHolder.close(); + } + } + + private void abortConnection() throws IOException { if (this.connHolder != null) { this.connHolder.abortConnection(); } @@ -69,13 +75,7 @@ private void cleanup() { public void releaseConnection() throws IOException { if (this.connHolder != null) { - try { - if (this.connHolder.isReusable()) { - this.connHolder.releaseConnection(); - } - } finally { - cleanup(); - } + this.connHolder.releaseConnection(); } } @@ -100,6 +100,12 @@ public void writeTo(final OutputStream outstream) throws IOException { try { this.wrappedEntity.writeTo(outstream); releaseConnection(); + } catch (IOException ex) { + abortConnection(); + throw ex; + } catch (RuntimeException ex) { + abortConnection(); + throw ex; } finally { cleanup(); } @@ -112,6 +118,12 @@ public boolean eofDetected(final InputStream wrapped) throws IOException { // reading trailers after the response body: wrapped.close(); releaseConnection(); + } catch (IOException ex) { + abortConnection(); + throw ex; + } catch (RuntimeException ex) { + abortConnection(); + throw ex; } finally { cleanup(); } @@ -132,6 +144,12 @@ public boolean streamClosed(final InputStream wrapped) throws IOException { throw ex; } } + } catch (IOException ex) { + abortConnection(); + throw ex; + } catch (RuntimeException ex) { + abortConnection(); + throw ex; } finally { cleanup(); } diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java index 70e23a815a..2261da82ba 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java @@ -305,7 +305,7 @@ public void testExecRequestConnectionRelease() throws Exception { Mockito.verify(connManager, Mockito.times(1)).releaseConnection( managedConn, null, 0, TimeUnit.MILLISECONDS); - Mockito.verify(managedConn, Mockito.times(1)).shutdown(); + Mockito.verify(managedConn, Mockito.times(1)).close(); } @Test diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestMinimalClientExec.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestMinimalClientExec.java index 7c79f148ba..9a96ba686c 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestMinimalClientExec.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestMinimalClientExec.java @@ -202,7 +202,7 @@ public void testExecRequestConnectionRelease() throws Exception { Mockito.verify(connManager, Mockito.times(1)).releaseConnection( managedConn, null, 0, TimeUnit.MILLISECONDS); - Mockito.verify(managedConn, Mockito.times(1)).shutdown(); + Mockito.verify(managedConn, Mockito.times(1)).close(); } @Test diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java index 00c06d1606..803cb94cd9 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java @@ -85,7 +85,7 @@ public void testEntityStreamClosedIOErrorAlreadyReleased() throws Exception { Mockito.when(connHolder.isReleased()).thenReturn(true); Mockito.doThrow(new SocketException()).when(instream).close(); EntityUtils.consume(wrapper); - Mockito.verify(connHolder).abortConnection(); + Mockito.verify(connHolder).close(); } @Test From c6be20feb0a5e2a9c24fc68653b2e315b73f0f7c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 13 Jun 2015 16:31:15 +0000 Subject: [PATCH 014/204] HTTPCLIENT-1658: fixed regression in RequestBuilder#copy git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1685285 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/client/methods/RequestBuilder.java | 21 ++----------------- .../client/methods/TestRequestBuilder.java | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java index 763bcb5119..dcd3e6989a 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java @@ -293,26 +293,9 @@ private RequestBuilder doCopy(final HttpRequest request) { final URI originalUri; if (request instanceof HttpUriRequest) { - originalUri = ((HttpUriRequest) request).getURI(); + uri = ((HttpUriRequest) request).getURI(); } else { - originalUri = URI.create(request.getRequestLine().getUri()); - } - - final URIBuilder uriBuilder = new URIBuilder(originalUri); - if (parameters == null) { - final List queryParams = uriBuilder.getQueryParams(); - if (!queryParams.isEmpty()) { - parameters = queryParams; - uriBuilder.clearParameters(); - } else { - parameters = null; - } - } - try { - uri = uriBuilder.build(); - } catch (URISyntaxException ex) { - // Should never happen - uri = originalUri; + uri = URI.create(request.getRequestLine().getUri()); } if (request instanceof Configurable) { diff --git a/httpclient/src/test/java/org/apache/http/client/methods/TestRequestBuilder.java b/httpclient/src/test/java/org/apache/http/client/methods/TestRequestBuilder.java index f839268983..84fea770d3 100644 --- a/httpclient/src/test/java/org/apache/http/client/methods/TestRequestBuilder.java +++ b/httpclient/src/test/java/org/apache/http/client/methods/TestRequestBuilder.java @@ -33,6 +33,7 @@ import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpRequest; import org.apache.http.HttpVersion; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; @@ -168,10 +169,8 @@ public void testCopyWithQueryParams() throws Exception { final RequestBuilder builder = RequestBuilder.copy(get); final List parameters = builder.getParameters(); Assert.assertNotNull(parameters); - Assert.assertEquals(2, parameters.size()); - Assert.assertEquals(new BasicNameValuePair("p1", "this"), parameters.get(0)); - Assert.assertEquals(new BasicNameValuePair("p2", "that"), parameters.get(1)); - Assert.assertEquals(new URI("/stuff"), builder.getUri()); + Assert.assertEquals(0, parameters.size()); + Assert.assertEquals(new URI("/stuff?p1=this&p2=that"), builder.getUri()); } @Test @@ -196,12 +195,20 @@ public void testCopyWithStringEntity() throws Exception { final RequestBuilder builder = RequestBuilder.copy(post); final List parameters = builder.getParameters(); Assert.assertNotNull(parameters); - Assert.assertEquals(1, parameters.size()); - Assert.assertEquals(new BasicNameValuePair("p1", "wtf"), parameters.get(0)); - Assert.assertEquals(new URI("/stuff"), builder.getUri()); + Assert.assertEquals(0, parameters.size()); + Assert.assertEquals(new URI("/stuff?p1=wtf"), builder.getUri()); Assert.assertSame(entity, builder.getEntity()); } + @Test + public void testCopyAndSetUri() throws Exception { + final URI uri1 = URI.create("http://host1.com/path?param=something"); + final URI uri2 = URI.create("http://host2.com/path?param=somethingdifferent"); + final HttpRequest request1 = new HttpGet(uri1); + final HttpUriRequest request2 = RequestBuilder.copy(request1).setUri(uri2).build(); + Assert.assertEquals(request2.getURI(), uri2); + } + @Test public void testGettersAndMutators() throws Exception { final HttpEntity entity = new StringEntity("stuff"); From 3b94921d03316330de1180b4bacb16ebf7eb99d0 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 23 Jul 2015 15:25:56 +0000 Subject: [PATCH 015/204] HTTPCLIENT-1667: RequestBuilder does not take charset into account when creating UrlEncodedFormEntity Contributed by Sergey Smith git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1692404 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/client/methods/RequestBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java index dcd3e6989a..9c00b5da6d 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java @@ -463,7 +463,7 @@ public HttpUriRequest build() { if (parameters != null && !parameters.isEmpty()) { if (entityCopy == null && (HttpPost.METHOD_NAME.equalsIgnoreCase(method) || HttpPut.METHOD_NAME.equalsIgnoreCase(method))) { - entityCopy = new UrlEncodedFormEntity(parameters, HTTP.DEF_CONTENT_CHARSET); + entityCopy = new UrlEncodedFormEntity(parameters, charset != null ? charset : HTTP.DEF_CONTENT_CHARSET); } else { try { uriNotNull = new URIBuilder(uriNotNull) From bd29207ff9db2e85e2bd8a97b2589cb247d96b89 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 24 Jul 2015 08:56:26 +0000 Subject: [PATCH 016/204] HTTPCLIENT-1668: Fluent request incorrectly handles connect timeout setting git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1692467 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/java/org/apache/http/client/fluent/Request.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java index 8d7136d015..593cee8a41 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java @@ -163,7 +163,7 @@ HttpResponse internalExecute( builder.setSocketTimeout(this.socketTmeout); } if (this.connectTimeout != null) { - builder.setSocketTimeout(this.connectTimeout); + builder.setConnectTimeout(this.connectTimeout); } if (this.proxy != null) { builder.setProxy(this.proxy); From 369b375c3bbc71f7e84b10e9221be15269fb20ca Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 7 Aug 2015 07:33:11 +0000 Subject: [PATCH 017/204] Use httpbin.org in examples git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1694618 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/examples/client/ClientAbortMethod.java | 2 +- .../examples/client/ClientAuthentication.java | 8 ++++---- .../examples/client/ClientChunkEncodedPost.java | 4 ++-- .../http/examples/client/ClientConfiguration.java | 9 +++------ .../examples/client/ClientConnectionRelease.java | 2 +- .../http/examples/client/ClientCustomContext.java | 2 +- .../client/ClientCustomPublicSuffixList.java | 2 +- .../http/examples/client/ClientCustomSSL.java | 4 ++-- .../client/ClientEvictExpiredConnections.java | 2 +- .../http/examples/client/ClientExecuteProxy.java | 4 ++-- .../http/examples/client/ClientExecuteSOCKS.java | 2 +- .../ClientPreemptiveBasicAuthentication.java | 8 ++++---- .../ClientPreemptiveDigestAuthentication.java | 8 ++++---- .../client/ClientProxyAuthentication.java | 15 +++++++++------ .../examples/client/ClientWithRequestFuture.java | 8 ++++---- .../client/ClientWithResponseHandler.java | 2 +- .../apache/http/examples/client/QuickStart.java | 4 ++-- .../src/test/resources/commons-logging.properties | 2 +- 18 files changed, 44 insertions(+), 44 deletions(-) diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientAbortMethod.java b/httpclient/src/examples/org/apache/http/examples/client/ClientAbortMethod.java index c92ac9ef7f..1b01f1c3f9 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientAbortMethod.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientAbortMethod.java @@ -40,7 +40,7 @@ public class ClientAbortMethod { public final static void main(String[] args) throws Exception { CloseableHttpClient httpclient = HttpClients.createDefault(); try { - HttpGet httpget = new HttpGet("http://www.apache.org/"); + HttpGet httpget = new HttpGet("http://httpbin.org/get"); System.out.println("Executing request " + httpget.getURI()); CloseableHttpResponse response = httpclient.execute(httpget); diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientAuthentication.java b/httpclient/src/examples/org/apache/http/examples/client/ClientAuthentication.java index e4c50e7db6..d4c8fc8505 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientAuthentication.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientAuthentication.java @@ -45,20 +45,20 @@ public class ClientAuthentication { public static void main(String[] args) throws Exception { CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( - new AuthScope("localhost", 443), - new UsernamePasswordCredentials("username", "password")); + new AuthScope("httpbin.org", 80), + new UsernamePasswordCredentials("user", "passwd")); CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider) .build(); try { - HttpGet httpget = new HttpGet("http://localhost/"); + HttpGet httpget = new HttpGet("http://httpbin.org/basic-auth/user/passwd"); System.out.println("Executing request " + httpget.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httpget); try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - EntityUtils.consume(response.getEntity()); + System.out.println(EntityUtils.toString(response.getEntity())); } finally { response.close(); } diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientChunkEncodedPost.java b/httpclient/src/examples/org/apache/http/examples/client/ClientChunkEncodedPost.java index dbf4d89663..39a4fad009 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientChunkEncodedPost.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientChunkEncodedPost.java @@ -49,7 +49,7 @@ public static void main(String[] args) throws Exception { } CloseableHttpClient httpclient = HttpClients.createDefault(); try { - HttpPost httppost = new HttpPost("http://localhost/"); + HttpPost httppost = new HttpPost("http://httpbin.org/post"); File file = new File(args[0]); @@ -69,7 +69,7 @@ public static void main(String[] args) throws Exception { try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - EntityUtils.consume(response.getEntity()); + System.out.println(EntityUtils.toString(response.getEntity())); } finally { response.close(); } diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java index ac6aa394c6..4ad7230a7c 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java @@ -81,6 +81,7 @@ import org.apache.http.message.LineParser; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.CharArrayBuffer; +import org.apache.http.util.EntityUtils; /** * This example demonstrates how to customize and configure the most common aspects @@ -221,7 +222,7 @@ public InetAddress[] resolve(final String host) throws UnknownHostException { .build(); try { - HttpGet httpget = new HttpGet("http://www.apache.org/"); + HttpGet httpget = new HttpGet("http://httpbin.org/get"); // Request configuration can be overridden at the request level. // They will take precedence over the one set at the client level. RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig) @@ -242,13 +243,9 @@ public InetAddress[] resolve(final String host) throws UnknownHostException { System.out.println("executing request " + httpget.getURI()); CloseableHttpResponse response = httpclient.execute(httpget, context); try { - HttpEntity entity = response.getEntity(); - System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - if (entity != null) { - System.out.println("Response content length: " + entity.getContentLength()); - } + System.out.println(EntityUtils.toString(response.getEntity())); System.out.println("----------------------------------------"); // Once the request has been executed the local context can diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java b/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java index 84d680d53b..65ee4bfccc 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java @@ -45,7 +45,7 @@ public class ClientConnectionRelease { public final static void main(String[] args) throws Exception { CloseableHttpClient httpclient = HttpClients.createDefault(); try { - HttpGet httpget = new HttpGet("http://localhost/"); + HttpGet httpget = new HttpGet("http://httpbin.org/get"); System.out.println("Executing request " + httpget.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httpget); diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientCustomContext.java b/httpclient/src/examples/org/apache/http/examples/client/ClientCustomContext.java index 19757624c0..a3d14b4655 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientCustomContext.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientCustomContext.java @@ -56,7 +56,7 @@ public final static void main(String[] args) throws Exception { // Bind custom cookie store to the local context localContext.setCookieStore(cookieStore); - HttpGet httpget = new HttpGet("http://localhost/"); + HttpGet httpget = new HttpGet("http://httpbin.org/cookies"); System.out.println("Executing request " + httpget.getRequestLine()); // Pass local context as a parameter diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientCustomPublicSuffixList.java b/httpclient/src/examples/org/apache/http/examples/client/ClientCustomPublicSuffixList.java index 0246caf599..5f52cd8b8d 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientCustomPublicSuffixList.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientCustomPublicSuffixList.java @@ -73,7 +73,7 @@ public final static void main(String[] args) throws Exception { .build(); try { - HttpGet httpget = new HttpGet("https://remotehost/"); + HttpGet httpget = new HttpGet("https://httpbin.org/"); System.out.println("executing request " + httpget.getRequestLine()); diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientCustomSSL.java b/httpclient/src/examples/org/apache/http/examples/client/ClientCustomSSL.java index eb162873a9..fbcf71b16b 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientCustomSSL.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientCustomSSL.java @@ -63,9 +63,9 @@ public final static void main(String[] args) throws Exception { .build(); try { - HttpGet httpget = new HttpGet("https://localhost/"); + HttpGet httpget = new HttpGet("https://httpbin.org/"); - System.out.println("executing request " + httpget.getRequestLine()); + System.out.println("Executing request " + httpget.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httpget); try { diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientEvictExpiredConnections.java b/httpclient/src/examples/org/apache/http/examples/client/ClientEvictExpiredConnections.java index b349709ac4..2c788ac69b 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientEvictExpiredConnections.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientEvictExpiredConnections.java @@ -68,7 +68,7 @@ public static void main(String[] args) throws Exception { try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - EntityUtils.consume(response.getEntity()); + System.out.println(EntityUtils.toString(response.getEntity())); } finally { response.close(); } diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteProxy.java b/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteProxy.java index e2740db328..33cc2ba043 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteProxy.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteProxy.java @@ -45,7 +45,7 @@ public class ClientExecuteProxy { public static void main(String[] args)throws Exception { CloseableHttpClient httpclient = HttpClients.createDefault(); try { - HttpHost target = new HttpHost("localhost", 443, "https"); + HttpHost target = new HttpHost("httpbin.org", 443, "https"); HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http"); RequestConfig config = RequestConfig.custom() @@ -60,7 +60,7 @@ public static void main(String[] args)throws Exception { try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - EntityUtils.consume(response.getEntity()); + System.out.println(EntityUtils.toString(response.getEntity())); } finally { response.close(); } diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteSOCKS.java b/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteSOCKS.java index 3cf62d768a..04ec10ccca 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteSOCKS.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteSOCKS.java @@ -67,7 +67,7 @@ public static void main(String[] args)throws Exception { HttpClientContext context = HttpClientContext.create(); context.setAttribute("socks.address", socksaddr); - HttpHost target = new HttpHost("localhost", 80, "http"); + HttpHost target = new HttpHost("httpbin.org", 80, "http"); HttpGet request = new HttpGet("/"); System.out.println("Executing request " + request + " to " + target + " via SOCKS proxy " + socksaddr); diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java b/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java index b0986cd6d2..d43b35c7bd 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java @@ -52,11 +52,11 @@ public class ClientPreemptiveBasicAuthentication { public static void main(String[] args) throws Exception { - HttpHost target = new HttpHost("localhost", 80, "http"); + HttpHost target = new HttpHost("httpbin.org", 80, "http"); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( new AuthScope(target.getHostName(), target.getPort()), - new UsernamePasswordCredentials("username", "password")); + new UsernamePasswordCredentials("user", "passwd")); CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider).build(); try { @@ -72,7 +72,7 @@ public static void main(String[] args) throws Exception { HttpClientContext localContext = HttpClientContext.create(); localContext.setAuthCache(authCache); - HttpGet httpget = new HttpGet("/"); + HttpGet httpget = new HttpGet("http://httpbin.org/hidden-basic-auth/user/passwd"); System.out.println("Executing request " + httpget.getRequestLine() + " to target " + target); for (int i = 0; i < 3; i++) { @@ -80,7 +80,7 @@ public static void main(String[] args) throws Exception { try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - EntityUtils.consume(response.getEntity()); + System.out.println(EntityUtils.toString(response.getEntity())); } finally { response.close(); } diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveDigestAuthentication.java b/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveDigestAuthentication.java index fd2e1182a9..0bec3e95d1 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveDigestAuthentication.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveDigestAuthentication.java @@ -53,11 +53,11 @@ public class ClientPreemptiveDigestAuthentication { public static void main(String[] args) throws Exception { - HttpHost target = new HttpHost("localhost", 80, "http"); + HttpHost target = new HttpHost("httpbin.org", 80, "http"); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( new AuthScope(target.getHostName(), target.getPort()), - new UsernamePasswordCredentials("username", "password")); + new UsernamePasswordCredentials("user", "passwd")); CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider) .build(); @@ -78,7 +78,7 @@ public static void main(String[] args) throws Exception { HttpClientContext localContext = HttpClientContext.create(); localContext.setAuthCache(authCache); - HttpGet httpget = new HttpGet("/"); + HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/user/passwd"); System.out.println("Executing request " + httpget.getRequestLine() + " to target " + target); for (int i = 0; i < 3; i++) { @@ -86,7 +86,7 @@ public static void main(String[] args) throws Exception { try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - EntityUtils.consume(response.getEntity()); + System.out.println(EntityUtils.toString(response.getEntity())); } finally { response.close(); } diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientProxyAuthentication.java b/httpclient/src/examples/org/apache/http/examples/client/ClientProxyAuthentication.java index d4431f148c..a3e83b541f 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientProxyAuthentication.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientProxyAuthentication.java @@ -47,18 +47,21 @@ public class ClientProxyAuthentication { public static void main(String[] args) throws Exception { CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( - new AuthScope("localhost", 8080), - new UsernamePasswordCredentials("username", "password")); + new AuthScope("localhost", 8888), + new UsernamePasswordCredentials("squid", "squid")); + credsProvider.setCredentials( + new AuthScope("httpbin.org", 80), + new UsernamePasswordCredentials("user", "passwd")); CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider).build(); try { - HttpHost target = new HttpHost("www.verisign.com", 443, "https"); - HttpHost proxy = new HttpHost("localhost", 8080); + HttpHost target = new HttpHost("httpbin.org", 80, "http"); + HttpHost proxy = new HttpHost("localhost", 8888); RequestConfig config = RequestConfig.custom() .setProxy(proxy) .build(); - HttpGet httpget = new HttpGet("/"); + HttpGet httpget = new HttpGet("/basic-auth/user/passwd"); httpget.setConfig(config); System.out.println("Executing request " + httpget.getRequestLine() + " to " + target + " via " + proxy); @@ -67,7 +70,7 @@ public static void main(String[] args) throws Exception { try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); - EntityUtils.consume(response.getEntity()); + System.out.println(EntityUtils.toString(response.getEntity())); } finally { response.close(); } diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientWithRequestFuture.java b/httpclient/src/examples/org/apache/http/examples/client/ClientWithRequestFuture.java index e9f9740b02..41328185a6 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientWithRequestFuture.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientWithRequestFuture.java @@ -64,7 +64,7 @@ public Boolean handleResponse(HttpResponse response) throws ClientProtocolExcept }; // Simple request ... - HttpGet request1 = new HttpGet("http://google.com"); + HttpGet request1 = new HttpGet("http://httpbin.org/get"); HttpRequestFutureTask futureTask1 = requestExecService.execute(request1, HttpClientContext.create(), handler); Boolean wasItOk1 = futureTask1.get(); @@ -72,7 +72,7 @@ public Boolean handleResponse(HttpResponse response) throws ClientProtocolExcept // Cancel a request try { - HttpGet request2 = new HttpGet("http://google.com"); + HttpGet request2 = new HttpGet("http://httpbin.org/get"); HttpRequestFutureTask futureTask2 = requestExecService.execute(request2, HttpClientContext.create(), handler); futureTask2.cancel(true); @@ -83,7 +83,7 @@ public Boolean handleResponse(HttpResponse response) throws ClientProtocolExcept } // Request with a timeout - HttpGet request3 = new HttpGet("http://google.com"); + HttpGet request3 = new HttpGet("http://httpbin.org/get"); HttpRequestFutureTask futureTask3 = requestExecService.execute(request3, HttpClientContext.create(), handler); Boolean wasItOk3 = futureTask3.get(10, TimeUnit.SECONDS); @@ -107,7 +107,7 @@ public void cancelled() { }; // Simple request with a callback - HttpGet request4 = new HttpGet("http://google.com"); + HttpGet request4 = new HttpGet("http://httpbin.org/get"); // using a null HttpContext here since it is optional // the callback will be called when the task completes, fails, or is cancelled HttpRequestFutureTask futureTask4 = requestExecService.execute(request4, diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientWithResponseHandler.java b/httpclient/src/examples/org/apache/http/examples/client/ClientWithResponseHandler.java index 401fdc99f7..ec58d589b0 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientWithResponseHandler.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientWithResponseHandler.java @@ -47,7 +47,7 @@ public class ClientWithResponseHandler { public final static void main(String[] args) throws Exception { CloseableHttpClient httpclient = HttpClients.createDefault(); try { - HttpGet httpget = new HttpGet("http://localhost/"); + HttpGet httpget = new HttpGet("http://httpbin.org/"); System.out.println("Executing request " + httpget.getRequestLine()); diff --git a/httpclient/src/examples/org/apache/http/examples/client/QuickStart.java b/httpclient/src/examples/org/apache/http/examples/client/QuickStart.java index dd5863adf2..cf5fed1c8a 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/QuickStart.java +++ b/httpclient/src/examples/org/apache/http/examples/client/QuickStart.java @@ -45,7 +45,7 @@ public class QuickStart { public static void main(String[] args) throws Exception { CloseableHttpClient httpclient = HttpClients.createDefault(); try { - HttpGet httpGet = new HttpGet("http://targethost/homepage"); + HttpGet httpGet = new HttpGet("http://httpbin.org/get"); CloseableHttpResponse response1 = httpclient.execute(httpGet); // The underlying HTTP connection is still held by the response object // to allow the response content to be streamed directly from the network socket. @@ -64,7 +64,7 @@ public static void main(String[] args) throws Exception { response1.close(); } - HttpPost httpPost = new HttpPost("http://targethost/login"); + HttpPost httpPost = new HttpPost("http://httpbin.org/post"); List nvps = new ArrayList (); nvps.add(new BasicNameValuePair("username", "vip")); nvps.add(new BasicNameValuePair("password", "secret")); diff --git a/httpclient/src/test/resources/commons-logging.properties b/httpclient/src/test/resources/commons-logging.properties index 2fa1b3b729..831ac3669c 100644 --- a/httpclient/src/test/resources/commons-logging.properties +++ b/httpclient/src/test/resources/commons-logging.properties @@ -23,4 +23,4 @@ # . # Disable logging for unit tests -org.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog +# org.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog From ab3bdf022910c1fbd2221d2c1d598f142dadd1d9 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 7 Aug 2015 07:40:08 +0000 Subject: [PATCH 018/204] HTTPCLIENT-1674: fixed project url in pom.xml git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1694624 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 815cce92c7..bfcb81d007 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ Apache HttpComponents Client 4.5.1-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services - http://hc.apache.org/httpcomponents-client + http://hc.apache.org/httpcomponents-client-ga/ 1999 pom From dee78eca68ec4f6f907b7b0ac5ab93fec6fe880c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 7 Aug 2015 18:51:38 +0000 Subject: [PATCH 019/204] Removed unused import git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1694729 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/examples/client/ClientConfiguration.java | 1 - httpclient/src/test/resources/commons-logging.properties | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java index 4ad7230a7c..af1c1a5c7a 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java @@ -36,7 +36,6 @@ import org.apache.http.Consts; import org.apache.http.Header; -import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; diff --git a/httpclient/src/test/resources/commons-logging.properties b/httpclient/src/test/resources/commons-logging.properties index 831ac3669c..2fa1b3b729 100644 --- a/httpclient/src/test/resources/commons-logging.properties +++ b/httpclient/src/test/resources/commons-logging.properties @@ -23,4 +23,4 @@ # . # Disable logging for unit tests -# org.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog +org.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog From 795a092dbd572f15b3f2d33203415e2b8bf9f2a9 Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Tue, 11 Aug 2015 10:00:42 +0000 Subject: [PATCH 020/204] Correct spelling of user 'principal' in the documentation git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1695238 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 2 +- .../apache/http/impl/auth/win/TestWindowsNegotiateScheme.java | 2 +- .../org/apache/http/impl/client/DefaultUserTokenHandler.java | 2 +- src/docbkx/advanced.xml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 5cabfbaa6d..c8c18d8d92 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -174,7 +174,7 @@ Changelog: * [HTTPCLIENT-1547] HttpClient OSGi bundle doesn't import the package "javax.naming". Contributed by Willem Jiang -* [HTTPCLIENT-1541] Use correct (HTTP/hostname) service principle name for Windows native +* [HTTPCLIENT-1541] Use correct (HTTP/hostname) service principal name for Windows native Negotiate/NTLM auth schemes. Contributed by Ka-Lok Fung diff --git a/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java b/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java index 6ff2d746be..1fea3f835f 100644 --- a/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java +++ b/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java @@ -91,7 +91,7 @@ public void testNoInfiniteLoopOnSPNOutsideDomain() throws Exception { Assume.assumeTrue("Test can only be run on Windows", WinHttpClients.isWinAuthAvailable()); // HTTPCLIENT-1545 - // If a service principle name (SPN) from outside your Windows domain tree (e.g., HTTP/example.com) is used, + // If a service principal name (SPN) from outside your Windows domain tree (e.g., HTTP/example.com) is used, // InitializeSecurityContext will return SEC_E_DOWNGRADE_DETECTED (decimal: -2146892976, hex: 0x80090350). // Because WindowsNegotiateScheme wasn't setting the completed state correctly when authentication fails, // HttpClient goes into an infinite loop, constantly retrying the negotiate authentication to kingdom diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java index 99fc92247a..e2a43c4b81 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java @@ -47,7 +47,7 @@ * persistent connections created with a particular user identity within * a particular security context can be reused by the same user only. *

- * DefaultUserTokenHandler will use the user principle of connection + * DefaultUserTokenHandler will use the user principal of connection * based authentication schemes such as NTLM or that of the SSL session * with the client authentication turned on. If both are unavailable, * {@code null} token will be returned. diff --git a/src/docbkx/advanced.xml b/src/docbkx/advanced.xml index a1bdf4e3ae..b97ca36a3f 100644 --- a/src/docbkx/advanced.xml +++ b/src/docbkx/advanced.xml @@ -1,7 +1,7 @@ - org.apache.httpcomponents - httpcore - provided + httpcore-osgi + ${httpcore.version} + + + org.apache.httpcomponents + httpcore-nio + + commons-codec commons-codec ${commons-codec.version} - compile org.apache.httpcomponents httpmime ${project.version} - compile org.apache.httpcomponents httpclient-cache ${project.version} - compile org.apache.httpcomponents fluent-hc ${project.version} - compile org.osgi org.osgi.core - 4.2.0 + ${osgi.framework.version} provided org.osgi org.osgi.compendium - 4.2.0 - provided + ${osgi.framework.version} @@ -98,6 +103,42 @@ junit test + + org.ops4j.pax.exam + pax-exam-container-native + ${pax.exam.version} + test + + + org.apache.felix + org.apache.felix.framework + 5.0.1 + test + + + org.ops4j.pax.exam + pax-exam-junit4 + test + ${pax.exam.version} + + + org.ops4j.pax.exam + pax-exam-link-mvn + test + ${pax.exam.version} + + + org.ops4j.pax.url + pax-url-aether + ${pax.url.version} + test + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + test + @@ -107,6 +148,29 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-bundles + generate-test-resources + + copy-dependencies + + + ${project.build.directory}/bundles + + org.slf4j + httpclient,httpmime,httpclient-cache,fluent-hc,httpcore,org.osgi.core + compile + + + + org.apache.felix maven-bundle-plugin @@ -121,7 +185,6 @@ org.apache.http.conn.*;version=${project.version}, org.apache.http.client.*;version=${project.version}, org.apache.http.entity.mime.*;version=${project.version}, - org.apache.http.entity.mime.content.*;version=${project.version}, org.apache.http.impl.auth.*;version=${project.version}, org.apache.http.impl.cookie.*;version=${project.version}, org.apache.http.impl.conn.*;version=${project.version}, @@ -174,6 +237,26 @@ true + + org.apache.maven.plugins + maven-failsafe-plugin + 2.18.1 + + + + integration-test + verify + + + + true + ${project.build.directory} + ${project.version} + + + + + org.apache.httpcomponents.httpclient_${project.version} diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java new file mode 100644 index 0000000000..f58acc0571 --- /dev/null +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java @@ -0,0 +1,93 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.osgi.impl; + +import org.apache.http.entity.mime.content.ByteArrayBody; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import java.io.File; +import java.io.FilenameFilter; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.List; + +import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.provision; +import static org.ops4j.pax.exam.CoreOptions.systemProperty; + +/** + * pax-exam test for the OSGi packaging of the client. + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class MimeExportedIT { + + @Configuration + public Option[] config() { + final String projectBuildDirectory = System.getProperty("project.build.directory", "target"); + final String projectVersion = System.getProperty("project.version"); + + final List bundleUrls = new ArrayList(); + final File bundleDir = new File(projectBuildDirectory, "bundles"); + final File[] bundleFiles = bundleDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(final File dir, final String name) { + return name.endsWith(".jar"); + } + }); + for (File bundleFile : bundleFiles) { + try { + bundleUrls.add(bundleFile.toURI().toURL().toExternalForm()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + bundleUrls.add(String.format("file:%s/org.apache.httpcomponents.httpclient_%s.jar", projectBuildDirectory, projectVersion)); + + final String[] bundles = bundleUrls.toArray(new String[bundleUrls.size()]); + return options( + provision(bundles), + junitBundles(), + systemProperty("pax.exam.osgi.unresolved.fail").value("true"), + systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN") + ); + } + + @Test + public void useContentBody() { + new ByteArrayBody(new byte[0], "filename.txt"); + } +} diff --git a/httpclient-osgi/src/test/resources/log4j.properties b/httpclient-osgi/src/test/resources/log4j.properties new file mode 100644 index 0000000000..9998ef530e --- /dev/null +++ b/httpclient-osgi/src/test/resources/log4j.properties @@ -0,0 +1,27 @@ +# * ==================================================================== +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# * ====================================================================\ + +log4j.rootLogger=WARN, A1 + +# A1 is set to be a ConsoleAppender. +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n From 2b3230123aa4a94652f50e8d3b8d93f2200545ac Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 16 Aug 2015 14:19:04 +0000 Subject: [PATCH 023/204] HTTPCLIENT-1673: make the test case a bit more substantial. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1696143 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/osgi/impl/MimeExportedIT.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java index f58acc0571..2f27829cf1 100644 --- a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java @@ -27,7 +27,12 @@ package org.apache.http.osgi.impl; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.ByteArrayBody; +import org.apache.http.entity.mime.content.StringBody; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; @@ -88,6 +93,17 @@ public boolean accept(final File dir, final String name) { @Test public void useContentBody() { - new ByteArrayBody(new byte[0], "filename.txt"); + final HttpPost httppost = new HttpPost("http://localhost:8181/cxf/annotator/annotate"); + httppost.addHeader("Accept", "application/json"); + final StringBody options = new StringBody("{}", ContentType.APPLICATION_JSON); + final byte[] atData = new byte[] { 1 }; + final ByteArrayBody bab = new ByteArrayBody(atData, ContentType.APPLICATION_JSON, "at.json"); + + final HttpEntity reqEntity = MultipartEntityBuilder.create() + .setContentType(ContentType.create("multipart/mixed")) + .addPart("options", options) + .addPart("text", bab) + .build(); + httppost.setEntity(reqEntity); } } From 3ae055638f5993ae7c2c644865301e23cd34fb9f Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Wed, 19 Aug 2015 13:02:54 +0000 Subject: [PATCH 024/204] HTTPCLIENT-1106: Use character arrays for passwords in Credentials objects, not Strings Deprecate constructors using String-based passwords git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1696576 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/java/org/apache/http/auth/NTCredentials.java | 3 ++- .../java/org/apache/http/auth/UsernamePasswordCredentials.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java b/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java index b0a0c4e7ca..3ce343fb3c 100644 --- a/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java @@ -59,6 +59,7 @@ public class NTCredentials implements Credentials, Serializable { * string argument. * * @param usernamePassword the domain/username:password formed string + * @deprecated (4.5) will be replaced with {@code String}, {@code char[]} in 5.0 */ public NTCredentials(final String usernamePassword) { super(); @@ -88,7 +89,7 @@ public NTCredentials(final String usernamePassword) { /** * Constructor. * @param userName The user name. This should not include the domain to authenticate with. - * For example: "user" is correct whereas "DOMAIN\\user" is not. + * For example: "user" is correct whereas "DOMAIN\user" is not. * @param password The password. * @param workstation The workstation the authentication request is originating from. * Essentially, the computer name for this machine. diff --git a/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java b/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java index e2f45c0521..e31d036f3c 100644 --- a/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java @@ -52,6 +52,7 @@ public class UsernamePasswordCredentials implements Credentials, Serializable { * * @param usernamePassword the username:password formed string * @see #toString + * @deprecated (4.5) will be replaced with {@code String}, {@code char[]} in 5.0 */ public UsernamePasswordCredentials(final String usernamePassword) { super(); From c0938e1f5592f77995c713c4897e87a596d9084d Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 21 Aug 2015 13:34:01 +0000 Subject: [PATCH 025/204] Revert "HTTPCLIENT-1673: make the test case a bit more substantial." This reverts commit 2b3230123aa4a94652f50e8d3b8d93f2200545ac. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1696971 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/osgi/impl/MimeExportedIT.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java index 2f27829cf1..f58acc0571 100644 --- a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java @@ -27,12 +27,7 @@ package org.apache.http.osgi.impl; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.ByteArrayBody; -import org.apache.http.entity.mime.content.StringBody; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; @@ -93,17 +88,6 @@ public boolean accept(final File dir, final String name) { @Test public void useContentBody() { - final HttpPost httppost = new HttpPost("http://localhost:8181/cxf/annotator/annotate"); - httppost.addHeader("Accept", "application/json"); - final StringBody options = new StringBody("{}", ContentType.APPLICATION_JSON); - final byte[] atData = new byte[] { 1 }; - final ByteArrayBody bab = new ByteArrayBody(atData, ContentType.APPLICATION_JSON, "at.json"); - - final HttpEntity reqEntity = MultipartEntityBuilder.create() - .setContentType(ContentType.create("multipart/mixed")) - .addPart("options", options) - .addPart("text", bab) - .build(); - httppost.setEntity(reqEntity); + new ByteArrayBody(new byte[0], "filename.txt"); } } From 80ff3b2e27a5a99ead75845f9d8151246605c13b Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 21 Aug 2015 13:35:04 +0000 Subject: [PATCH 026/204] Revert "HTTPCLIENT-1673: revert change, which was not necessary" This reverts commit 7f66d5dc61651cd2f024901e5f9243d72fe361a4. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1696973 13f79535-47bb-0310-9956-ffa450edef68 --- httpclient-osgi/pom.xml | 105 ++---------------- .../apache/http/osgi/impl/MimeExportedIT.java | 93 ---------------- .../src/test/resources/log4j.properties | 27 ----- 3 files changed, 11 insertions(+), 214 deletions(-) delete mode 100644 httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java delete mode 100644 httpclient-osgi/src/test/resources/log4j.properties diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index c7a898f6e4..5569b8cadb 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -42,10 +42,6 @@ "[4.4.0, 4.5.0)" "[1.1.0, 1.3.0)" - 2.4.1 - 4.5.0 - 5.0.0 - 1.7.5 @@ -53,49 +49,48 @@ org.apache.httpcomponents httpclient ${project.version} + compile - org.apache.httpcomponents - httpcore-osgi - ${httpcore.version} - - - org.apache.httpcomponents - httpcore-nio - - + httpcore + provided commons-codec commons-codec ${commons-codec.version} + compile org.apache.httpcomponents httpmime ${project.version} + compile org.apache.httpcomponents httpclient-cache ${project.version} + compile org.apache.httpcomponents fluent-hc ${project.version} + compile org.osgi org.osgi.core - ${osgi.framework.version} + 4.2.0 provided org.osgi org.osgi.compendium - ${osgi.framework.version} + 4.2.0 + provided @@ -103,42 +98,6 @@ junit test - - org.ops4j.pax.exam - pax-exam-container-native - ${pax.exam.version} - test - - - org.apache.felix - org.apache.felix.framework - 5.0.1 - test - - - org.ops4j.pax.exam - pax-exam-junit4 - test - ${pax.exam.version} - - - org.ops4j.pax.exam - pax-exam-link-mvn - test - ${pax.exam.version} - - - org.ops4j.pax.url - pax-url-aether - ${pax.url.version} - test - - - org.slf4j - slf4j-log4j12 - ${slf4j.version} - test - @@ -148,29 +107,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-bundles - generate-test-resources - - copy-dependencies - - - ${project.build.directory}/bundles - - org.slf4j - httpclient,httpmime,httpclient-cache,fluent-hc,httpcore,org.osgi.core - compile - - - - org.apache.felix maven-bundle-plugin @@ -185,6 +121,7 @@ org.apache.http.conn.*;version=${project.version}, org.apache.http.client.*;version=${project.version}, org.apache.http.entity.mime.*;version=${project.version}, + org.apache.http.entity.mime.content.*;version=${project.version}, org.apache.http.impl.auth.*;version=${project.version}, org.apache.http.impl.cookie.*;version=${project.version}, org.apache.http.impl.conn.*;version=${project.version}, @@ -237,26 +174,6 @@ true - - org.apache.maven.plugins - maven-failsafe-plugin - 2.18.1 - - - - integration-test - verify - - - - true - ${project.build.directory} - ${project.version} - - - - - org.apache.httpcomponents.httpclient_${project.version} diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java deleted file mode 100644 index f58acc0571..0000000000 --- a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/MimeExportedIT.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.osgi.impl; - -import org.apache.http.entity.mime.content.ByteArrayBody; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.ops4j.pax.exam.Configuration; -import org.ops4j.pax.exam.Option; -import org.ops4j.pax.exam.junit.PaxExam; -import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; -import org.ops4j.pax.exam.spi.reactors.PerClass; - -import java.io.File; -import java.io.FilenameFilter; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.List; - -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.options; -import static org.ops4j.pax.exam.CoreOptions.provision; -import static org.ops4j.pax.exam.CoreOptions.systemProperty; - -/** - * pax-exam test for the OSGi packaging of the client. - */ -@RunWith(PaxExam.class) -@ExamReactorStrategy(PerClass.class) -public class MimeExportedIT { - - @Configuration - public Option[] config() { - final String projectBuildDirectory = System.getProperty("project.build.directory", "target"); - final String projectVersion = System.getProperty("project.version"); - - final List bundleUrls = new ArrayList(); - final File bundleDir = new File(projectBuildDirectory, "bundles"); - final File[] bundleFiles = bundleDir.listFiles(new FilenameFilter() { - @Override - public boolean accept(final File dir, final String name) { - return name.endsWith(".jar"); - } - }); - for (File bundleFile : bundleFiles) { - try { - bundleUrls.add(bundleFile.toURI().toURL().toExternalForm()); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - - bundleUrls.add(String.format("file:%s/org.apache.httpcomponents.httpclient_%s.jar", projectBuildDirectory, projectVersion)); - - final String[] bundles = bundleUrls.toArray(new String[bundleUrls.size()]); - return options( - provision(bundles), - junitBundles(), - systemProperty("pax.exam.osgi.unresolved.fail").value("true"), - systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN") - ); - } - - @Test - public void useContentBody() { - new ByteArrayBody(new byte[0], "filename.txt"); - } -} diff --git a/httpclient-osgi/src/test/resources/log4j.properties b/httpclient-osgi/src/test/resources/log4j.properties deleted file mode 100644 index 9998ef530e..0000000000 --- a/httpclient-osgi/src/test/resources/log4j.properties +++ /dev/null @@ -1,27 +0,0 @@ -# * ==================================================================== -# * Licensed to the Apache Software Foundation (ASF) under one -# * or more contributor license agreements. See the NOTICE file -# * distributed with this work for additional information -# * regarding copyright ownership. The ASF licenses this file -# * to you under the Apache License, Version 2.0 (the -# * "License"); you may not use this file except in compliance -# * with the License. You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, -# * software distributed under the License is distributed on an -# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# * KIND, either express or implied. See the License for the -# * specific language governing permissions and limitations -# * under the License. -# * ====================================================================\ - -log4j.rootLogger=WARN, A1 - -# A1 is set to be a ConsoleAppender. -log4j.appender.A1=org.apache.log4j.ConsoleAppender - -# A1 uses PatternLayout. -log4j.appender.A1.layout=org.apache.log4j.PatternLayout -log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n From 6fd73b5fb52b44ef7670765a35d88cbf939b36a5 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 30 Aug 2015 16:34:38 +0000 Subject: [PATCH 027/204] HTTPCLIENT-1680: redirect of a POST request causes ClientProtocolException git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1700136 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/execchain/RedirectExec.java | 4 ++-- .../http/impl/execchain/TestRedirectExec.java | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java index f9c1d795f3..dcafdb55ca 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java @@ -111,7 +111,7 @@ public CloseableHttpResponse execute( currentRoute, currentRequest, context, execAware); try { if (config.isRedirectsEnabled() && - this.redirectStrategy.isRedirected(currentRequest, response, context)) { + this.redirectStrategy.isRedirected(currentRequest.getOriginal(), response, context)) { if (redirectCount >= maxRedirects) { throw new RedirectException("Maximum redirects ("+ maxRedirects + ") exceeded"); @@ -119,7 +119,7 @@ public CloseableHttpResponse execute( redirectCount++; final HttpRequest redirect = this.redirectStrategy.getRedirect( - currentRequest, response, context); + currentRequest.getOriginal(), response, context); if (!redirect.headerIterator().hasNext()) { final HttpRequest original = request.getOriginal(); redirect.setHeaders(original.getAllHeaders()); diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java index ed1546cb7d..5621a3f2c1 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java @@ -120,11 +120,11 @@ public void testFundamentals() throws Exception { Mockito.any(), Mockito.any())).thenReturn(response2); Mockito.when(redirectStrategy.isRedirected( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any())).thenReturn(Boolean.TRUE); Mockito.when(redirectStrategy.getRedirect( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any())).thenReturn(redirect); Mockito.when(httpRoutePlanner.determineRoute( @@ -216,11 +216,11 @@ public void testRelativeRedirect() throws Exception { Mockito.any(), Mockito.any())).thenReturn(response2); Mockito.when(redirectStrategy.isRedirected( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any())).thenReturn(Boolean.TRUE); Mockito.when(redirectStrategy.getRedirect( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any())).thenReturn(redirect); Mockito.when(httpRoutePlanner.determineRoute( @@ -240,10 +240,10 @@ public void testCrossSiteRedirect() throws Exception { final AuthState targetAuthState = new AuthState(); targetAuthState.setState(AuthProtocolState.SUCCESS); - targetAuthState.update(new BasicScheme(), new UsernamePasswordCredentials("user:pass")); + targetAuthState.update(new BasicScheme(), new UsernamePasswordCredentials("user", "pass")); final AuthState proxyAuthState = new AuthState(); proxyAuthState.setState(AuthProtocolState.SUCCESS); - proxyAuthState.update(new NTLMScheme(), new NTCredentials("user:pass")); + proxyAuthState.update(new NTLMScheme(), new NTCredentials("user", "pass", null, null)); context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, targetAuthState); context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState); @@ -261,11 +261,11 @@ public void testCrossSiteRedirect() throws Exception { Mockito.any(), Mockito.any())).thenReturn(response2); Mockito.when(redirectStrategy.isRedirected( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any())).thenReturn(Boolean.TRUE); Mockito.when(redirectStrategy.getRedirect( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any())).thenReturn(redirect); Mockito.when(httpRoutePlanner.determineRoute( @@ -332,11 +332,11 @@ public void testRedirectProtocolException() throws Exception { Mockito.any(), Mockito.any())).thenReturn(response1); Mockito.when(redirectStrategy.isRedirected( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any())).thenReturn(Boolean.TRUE); Mockito.doThrow(new ProtocolException("Oppsie")).when(redirectStrategy).getRedirect( - Mockito.same(request), + Mockito.same(get), Mockito.same(response1), Mockito.any()); From 8cf6df2c8ba7b6835116b783bfd05a0416d77b79 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 4 Sep 2015 13:47:05 +0000 Subject: [PATCH 028/204] Log socket timeout values git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1701258 13f79535-47bb-0310-9956-ffa450edef68 --- .../conn/LoggingManagedHttpClientConnection.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java index 75adb7a72a..2614b0c9bb 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java @@ -75,10 +75,21 @@ public LoggingManagedHttpClientConnection( @Override public void close() throws IOException { + + if (super.isOpen()) { + if (this.log.isDebugEnabled()) { + this.log.debug(getId() + ": Close connection"); + } + super.close(); + } + } + + @Override + public void setSocketTimeout(final int timeout) { if (this.log.isDebugEnabled()) { - this.log.debug(getId() + ": Close connection"); + this.log.debug(getId() + ": set socket timeout to " + timeout); } - super.close(); + super.setSocketTimeout(timeout); } @Override From abc894b3b86ab102371653993f65c51fb292a408 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 9 Sep 2015 16:52:37 +0000 Subject: [PATCH 029/204] Upgraded HttpCore to version 4.4.3 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1702055 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bfcb81d007..bbaf243ef3 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 1.6 1.6 - 4.4.1 + 4.4.3 1.2 1.9 2.6.9 From 3b9a03913bcdb7a1c1be70135c4a5f0ccefc963d Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 11 Sep 2015 12:28:36 +0000 Subject: [PATCH 030/204] Updated release notes for HttpClient 4.5.1 release git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1702444 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index c8c18d8d92..32c1c9691e 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,32 @@ +Release 4.5.1 +------------------- + +HttpClient 4.5.1 (GA) is a maintenance release that fixes a number of minor defects found since 4.5. + +Please note that as of 4.4 HttpClient requires Java 1.6 or newer. + +Changelog: +------------------- + +* [HTTPCLIENT-1680] redirect of a POST request causes ClientProtocolException. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1673] org.apache.http.entity.mime.content.* missing from OSGi exports. + Contributed by Benson Margulies + +* [HTTPCLIENT-1668] Fluent request incorrectly handles connect timeout setting. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1667] RequestBuilder does not take charset into account when creating + UrlEncodedFormEntity. + Contributed by Sergey Smith + +* [HTTPCLIENT-1655] HttpClient sends RST instead of FIN ACK sequence when using non-persistant + connections. + Contributed by Oleg Kalnichevski + + + Release 4.5 ------------------- From b6c1516e61a3e3658742fb0ce7362cf80223a230 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 15 Sep 2015 12:18:02 +0000 Subject: [PATCH 031/204] Upgraded HttpClient version to 4.5.2-SNAPSHOT git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1703168 13f79535-47bb-0310-9956-ffa450edef68 --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index e2b351628d..10dea485d9 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.1-SNAPSHOT + 4.5.2-SNAPSHOT fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index d2a84ff5e9..480eba362a 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.1-SNAPSHOT + 4.5.2-SNAPSHOT httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 5569b8cadb..e403f58108 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.1-SNAPSHOT + 4.5.2-SNAPSHOT httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index e7208bdaa8..89c2cdb8f0 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.1-SNAPSHOT + 4.5.2-SNAPSHOT httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 117a838332..985f53db08 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.1-SNAPSHOT + 4.5.2-SNAPSHOT httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index 3a0618fe2d..538e13703c 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.1-SNAPSHOT + 4.5.2-SNAPSHOT httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index bbaf243ef3..478ad22a4a 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.1-SNAPSHOT + 4.5.2-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 From e3232f5425be6b127c4d46c4bd8d9cd7b33724f5 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 3 Oct 2015 13:07:21 +0000 Subject: [PATCH 032/204] HTTPCLIENT-1685: PublicSuffixDomainFilter to ignore local hosts and local domains git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1706576 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/cookie/PublicSuffixDomainFilter.java | 31 ++++++++++++++++--- .../cookie/TestPublicSuffixListParser.java | 26 ++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java index 3e44ae89aa..2cafcf11ce 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java @@ -26,6 +26,9 @@ */ package org.apache.http.impl.cookie; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.http.annotation.Immutable; import org.apache.http.conn.util.PublicSuffixList; import org.apache.http.conn.util.PublicSuffixMatcher; @@ -52,11 +55,23 @@ public class PublicSuffixDomainFilter implements CommonCookieAttributeHandler { private final CommonCookieAttributeHandler handler; private final PublicSuffixMatcher publicSuffixMatcher; + private final Map localDomainMap; + + private static Map createLocalDomainMap() { + final ConcurrentHashMap map = new ConcurrentHashMap(); + map.put(".localhost.", Boolean.TRUE); // RFC 6761 + map.put(".test.", Boolean.TRUE); // RFC 6761 + map.put(".local.", Boolean.TRUE); // RFC 6762 + map.put(".local", Boolean.TRUE); + map.put(".localdomain", Boolean.TRUE); + return map; + } public PublicSuffixDomainFilter( final CommonCookieAttributeHandler handler, final PublicSuffixMatcher publicSuffixMatcher) { this.handler = Args.notNull(handler, "Cookie handler"); this.publicSuffixMatcher = Args.notNull(publicSuffixMatcher, "Public suffix matcher"); + this.localDomainMap = createLocalDomainMap(); } public PublicSuffixDomainFilter( @@ -65,6 +80,7 @@ public PublicSuffixDomainFilter( Args.notNull(suffixList, "Public suffix list"); this.handler = handler; this.publicSuffixMatcher = new PublicSuffixMatcher(suffixList.getRules(), suffixList.getExceptions()); + this.localDomainMap = createLocalDomainMap(); } /** @@ -72,12 +88,17 @@ public PublicSuffixDomainFilter( */ @Override public boolean match(final Cookie cookie, final CookieOrigin origin) { - final String domain = cookie.getDomain(); - if (!domain.equalsIgnoreCase("localhost") && publicSuffixMatcher.matches(domain)) { - return false; - } else { - return handler.match(cookie, origin); + final String host = cookie.getDomain(); + final int i = host.indexOf('.'); + if (i >= 0) { + final String domain = host.substring(i); + if (!this.localDomainMap.containsKey(domain)) { + if (this.publicSuffixMatcher.matches(host)) { + return false; + } + } } + return handler.match(cookie, origin); } @Override diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java index 86dded9288..50816ba2e1 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java @@ -78,6 +78,32 @@ public void testParse() throws Exception { Assert.assertTrue(filter.match(cookie, new CookieOrigin("apache.metro.tokyo.jp", 80, "/stuff", false))); } + @Test + public void testParseLocal() throws Exception { + final BasicClientCookie cookie = new BasicClientCookie("name", "value"); + + cookie.setDomain("localhost"); + Assert.assertTrue(filter.match(cookie, new CookieOrigin("localhost", 80, "/stuff", false))); + + cookie.setDomain("somehost"); + Assert.assertTrue(filter.match(cookie, new CookieOrigin("somehost", 80, "/stuff", false))); + + cookie.setDomain(".localdomain"); + Assert.assertTrue(filter.match(cookie, new CookieOrigin("somehost.localdomain", 80, "/stuff", false))); + + cookie.setDomain(".local."); + Assert.assertTrue(filter.match(cookie, new CookieOrigin("somehost.local.", 80, "/stuff", false))); + + cookie.setDomain(".localhost."); + Assert.assertTrue(filter.match(cookie, new CookieOrigin("somehost.localhost.", 80, "/stuff", false))); + + cookie.setDomain(".local"); + Assert.assertTrue(filter.match(cookie, new CookieOrigin("somehost.local", 80, "/stuff", false))); + + cookie.setDomain(".blah"); + Assert.assertFalse(filter.match(cookie, new CookieOrigin("somehost.blah", 80, "/stuff", false))); + } + @Test public void testUnicode() throws Exception { final BasicClientCookie cookie = new BasicClientCookie("name", "value"); From 2f062b3b43120c130064985cf7f5d34410574c10 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 3 Oct 2015 13:46:01 +0000 Subject: [PATCH 033/204] HTTPCLIENT-1685: PublicSuffixDomainFilter to ignore local hosts and local domains (follow-up) git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1706582 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/impl/cookie/PublicSuffixDomainFilter.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java index 2cafcf11ce..062f8ec6af 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java @@ -97,6 +97,12 @@ public boolean match(final Cookie cookie, final CookieOrigin origin) { return false; } } + } else { + if (!host.equalsIgnoreCase(origin.getHost())) { + if (this.publicSuffixMatcher.matches(host)) { + return false; + } + } } return handler.match(cookie, origin); } From 8e6ab0bdb8569ff1328fb7e7eeec10f3c21e2450 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 20 Oct 2015 07:42:34 +0000 Subject: [PATCH 034/204] HTTPCLIENT-1665: MultipartEntity to use US-ASCII charset by default (regression) git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1709523 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/entity/mime/MultipartEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java b/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java index 0a09ee78f1..07c43b6f28 100644 --- a/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java +++ b/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java @@ -70,7 +70,7 @@ public MultipartEntity( super(); this.builder = new MultipartEntityBuilder() .setMode(mode) - .setCharset(charset) + .setCharset(charset != null ? charset : MIME.DEFAULT_CHARSET) .setBoundary(boundary); this.entity = null; } From 09cefc2b8970eea56d81b1a886d9bb769a48daf3 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 21 Oct 2015 12:34:14 +0000 Subject: [PATCH 035/204] MultipartFormEntity#getContent implementation Contributed by Slikey git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1709814 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/entity/mime/MultipartFormEntity.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java b/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java index 467ca8e088..cabb824ae8 100644 --- a/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java +++ b/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java @@ -27,16 +27,19 @@ package org.apache.http.entity.mime; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.http.ContentTooLongException; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.entity.ContentType; import org.apache.http.message.BasicHeader; import org.apache.http.protocol.HTTP; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - @SuppressWarnings("deprecation") class MultipartFormEntity implements HttpEntity { @@ -94,8 +97,15 @@ public void consumeContent() { @Override public InputStream getContent() throws IOException { - throw new UnsupportedOperationException( - "Multipart form entity does not implement #getContent()"); + if (this.contentLength < 0) { + throw new ContentTooLongException("Content length is unknown"); + } else if (this.contentLength > 25 * 1024) { + throw new ContentTooLongException("Content length is too long: " + this.contentLength); + } + final ByteArrayOutputStream outstream = new ByteArrayOutputStream(); + writeTo(outstream); + outstream.flush(); + return new ByteArrayInputStream(outstream.toByteArray()); } @Override From 549c26f9580316c9f8a6a35ad4451a95a5e480d0 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 9 Nov 2015 13:18:30 +0000 Subject: [PATCH 036/204] HTTPCLIENT-1216: removed ThreadLocal subclass from DateUtils Contributed by Jochen Kemnade git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1713429 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/client/utils/DateUtils.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java index 326230ab94..a18fbd7244 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java @@ -200,15 +200,7 @@ private DateUtils() { final static class DateFormatHolder { private static final ThreadLocal>> - THREADLOCAL_FORMATS = new ThreadLocal>>() { - - @Override - protected SoftReference> initialValue() { - return new SoftReference>( - new HashMap()); - } - - }; + THREADLOCAL_FORMATS = new ThreadLocal>>(); /** * creates a {@link SimpleDateFormat} for the requested format string. @@ -224,7 +216,7 @@ protected SoftReference> initialValue() { */ public static SimpleDateFormat formatFor(final String pattern) { final SoftReference> ref = THREADLOCAL_FORMATS.get(); - Map formats = ref.get(); + Map formats = ref == null ? null : ref.get(); if (formats == null) { formats = new HashMap(); THREADLOCAL_FORMATS.set( From cd8c72626ff84964b21745b1241b87bcb1393d76 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 14 Nov 2015 20:45:32 +0000 Subject: [PATCH 037/204] HTTPCLIENT-1695: RFC 6265 compliant cookie spec to ignore cookies with empty name / missing value git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1714365 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/impl/cookie/RFC6265CookieSpec.java | 4 ++-- .../apache/http/impl/cookie/TestRFC6265CookieSpec.java | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java index 3e8e63c004..c9f9b99d30 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java @@ -130,10 +130,10 @@ public final List parse(final Header header, final CookieOrigin origin) } final String name = tokenParser.parseToken(buffer, cursor, TOKEN_DELIMS); if (name.length() == 0) { - throw new MalformedCookieException("Cookie name is invalid: '" + header.toString() + "'"); + return Collections.emptyList(); } if (cursor.atEnd()) { - throw new MalformedCookieException("Cookie value is invalid: '" + header.toString() + "'"); + return Collections.emptyList(); } final int valueDelim = buffer.charAt(cursor.getPos()); cursor.updatePos(cursor.getPos() + 1); diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java index 82e97a467a..fc6adf1670 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java @@ -98,22 +98,24 @@ public void testParseCookieWrongHeader() throws Exception { cookiespec.parse(header, origin); } - @Test(expected = MalformedCookieException.class) + @Test public void testParseCookieMissingName() throws Exception { final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(); final Header header = new BasicHeader("Set-Cookie", "=blah ; this = stuff;"); final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true); - cookiespec.parse(header, origin); + final List cookies = cookiespec.parse(header, origin); + Assert.assertEquals(0, cookies.size()); } - @Test(expected = MalformedCookieException.class) + @Test public void testParseCookieMissingValue1() throws Exception { final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(); final Header header = new BasicHeader("Set-Cookie", "blah"); final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true); - cookiespec.parse(header, origin); + final List cookies = cookiespec.parse(header, origin); + Assert.assertEquals(0, cookies.size()); } @Test(expected = MalformedCookieException.class) From 1b0cf671f227d0fe5d85e2197036b31c1bd55ce4 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 28 Nov 2015 13:25:56 +0000 Subject: [PATCH 038/204] HTTPCLIENT-1698: Fixed matching of IPv6 addresses by DefaultHostnameVerifier git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1716972 13f79535-47bb-0310-9956-ffa450edef68 --- .../conn/ssl/DefaultHostnameVerifier.java | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index e80bf3d209..8b9d52659c 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -64,6 +64,8 @@ @Immutable public final class DefaultHostnameVerifier implements HostnameVerifier { + enum TYPE { IPv4, IPv6, DNS }; + final static int DNS_NAME_TYPE = 2; final static int IP_ADDRESS_TYPE = 7; @@ -96,17 +98,30 @@ public boolean verify(final String host, final SSLSession session) { public void verify( final String host, final X509Certificate cert) throws SSLException { - final boolean ipv4 = InetAddressUtils.isIPv4Address(host); - final boolean ipv6 = InetAddressUtils.isIPv6Address(host); - final int subjectType = ipv4 || ipv6 ? IP_ADDRESS_TYPE : DNS_NAME_TYPE; + TYPE hostFormat = TYPE.DNS; + if (InetAddressUtils.isIPv4Address(host)) { + hostFormat = TYPE.IPv4; + } else { + String s = host; + if (s.startsWith("[") && s.endsWith("]")) { + s = host.substring(1, host.length() - 1); + } + if (InetAddressUtils.isIPv6Address(s)) { + hostFormat = TYPE.IPv6; + } + } + final int subjectType = hostFormat == TYPE.IPv4 || hostFormat == TYPE.IPv6 ? IP_ADDRESS_TYPE : DNS_NAME_TYPE; final List subjectAlts = extractSubjectAlts(cert, subjectType); if (subjectAlts != null && !subjectAlts.isEmpty()) { - if (ipv4) { - matchIPAddress(host, subjectAlts); - } else if (ipv6) { - matchIPv6Address(host, subjectAlts); - } else { - matchDNSName(host, subjectAlts, this.publicSuffixMatcher); + switch (hostFormat) { + case IPv4: + matchIPAddress(host, subjectAlts); + break; + case IPv6: + matchIPv6Address(host, subjectAlts); + break; + default: + matchDNSName(host, subjectAlts, this.publicSuffixMatcher); } } else { // CN matching has been deprecated by rfc2818 and can be used From 1c151cf38ac87dc7799630a038cd0c1bcce6920e Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 30 Nov 2015 20:34:24 +0000 Subject: [PATCH 039/204] HTTPCLIENT-1550: fixed 'deflate' zlib header check git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1717323 13f79535-47bb-0310-9956-ffa450edef68 --- .../client/entity/DeflateInputStream.java | 191 ++++++------------ .../http/client/entity/TestDeflate.java | 58 ++++++ .../apache/http/client/entity/TestGZip.java | 29 --- 3 files changed, 119 insertions(+), 159 deletions(-) create mode 100644 httpclient/src/test/java/org/apache/http/client/entity/TestDeflate.java diff --git a/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java index dfd8f4be47..24f7d048b3 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java @@ -29,179 +29,110 @@ import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; -import java.util.zip.DataFormatException; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; +import java.util.zip.ZipException; -/** Deflate input stream. This class includes logic needed for various Rfc's in order -* to reasonably implement the "deflate" compression style. -*/ -public class DeflateInputStream extends InputStream -{ - private InputStream sourceStream; - - public DeflateInputStream(final InputStream wrapped) - throws IOException - { - /* - * A zlib stream will have a header. - * - * CMF | FLG [| DICTID ] | ...compressed data | ADLER32 | - * - * * CMF is one byte. - * - * * FLG is one byte. - * - * * DICTID is four bytes, and only present if FLG.FDICT is set. - * - * Sniff the content. Does it look like a zlib stream, with a CMF, etc? c.f. RFC1950, - * section 2.2. http://tools.ietf.org/html/rfc1950#page-4 - * - * We need to see if it looks like a proper zlib stream, or whether it is just a deflate - * stream. RFC2616 calls zlib streams deflate. Confusing, isn't it? That's why some servers - * implement deflate Content-Encoding using deflate streams, rather than zlib streams. - * - * We could start looking at the bytes, but to be honest, someone else has already read - * the RFCs and implemented that for us. So we'll just use the JDK libraries and exception - * handling to do this. If that proves slow, then we could potentially change this to check - * the first byte - does it look like a CMF? What about the second byte - does it look like - * a FLG, etc. - */ - - /* We read a small buffer to sniff the content. */ - final byte[] peeked = new byte[6]; - - final PushbackInputStream pushback = new PushbackInputStream(wrapped, peeked.length); - - final int headerLength = pushback.read(peeked); - - if (headerLength == -1) { - throw new IOException("Unable to read the response"); - } - - /* We try to read the first uncompressed byte. */ - final byte[] dummy = new byte[1]; - - final Inflater inf = new Inflater(); - - try { - int n; - while ((n = inf.inflate(dummy)) == 0) { - if (inf.finished()) { - - /* Not expecting this, so fail loudly. */ - throw new IOException("Unable to read the response"); - } +/** + * Deflate input stream. This class includes logic needed for various Rfc's in order + * to reasonably implement the "deflate" compression style. + */ +public class DeflateInputStream extends InputStream { - if (inf.needsDictionary()) { + private InputStream sourceStream; - /* Need dictionary - then it must be zlib stream with DICTID part? */ - break; - } + public DeflateInputStream(final InputStream wrapped) throws IOException { - if (inf.needsInput()) { - inf.setInput(peeked); - } - } + final PushbackInputStream pushback = new PushbackInputStream(wrapped, 2); + final int i1 = pushback.read(); + final int i2 = pushback.read(); + if (i1 == -1 || i2 == -1) { + throw new ZipException("Unexpected end of stream"); + } - if (n == -1) { - throw new IOException("Unable to read the response"); - } + pushback.unread(i2); + pushback.unread(i1); - /* - * We read something without a problem, so it's a valid zlib stream. Just need to reset - * and return an unused InputStream now. - */ - pushback.unread(peeked, 0, headerLength); - sourceStream = new DeflateStream(pushback, new Inflater()); - } catch (final DataFormatException e) { - - /* Presume that it's an RFC1951 deflate stream rather than RFC1950 zlib stream and try - * again. */ - pushback.unread(peeked, 0, headerLength); - sourceStream = new DeflateStream(pushback, new Inflater(true)); - } finally { - inf.end(); + boolean nowrap = true; + final int b1 = i1 & 0xFF; + final int compressionMethod = b1 & 0xF; + final int compressionInfo = b1 >> 4 & 0xF; + final int b2 = i2 & 0xFF; + if (compressionMethod == 8 && compressionInfo <= 7 && ((b1 << 8) | b2) % 31 == 0) { + nowrap = false; } - + sourceStream = new DeflateStream(pushback, new Inflater(nowrap)); } - /** Read a byte. - */ + /** + * Read a byte. + */ @Override - public int read() - throws IOException - { + public int read() throws IOException { return sourceStream.read(); } - /** Read lots of bytes. - */ + /** + * Read lots of bytes. + */ @Override - public int read(final byte[] b) - throws IOException - { + public int read(final byte[] b) throws IOException { return sourceStream.read(b); } - /** Read lots of specific bytes. - */ + /** + * Read lots of specific bytes. + */ @Override - public int read(final byte[] b, final int off, final int len) - throws IOException - { - return sourceStream.read(b,off,len); + public int read(final byte[] b, final int off, final int len) throws IOException { + return sourceStream.read(b, off, len); } - /** Skip - */ + /** + * Skip + */ @Override - public long skip(final long n) - throws IOException - { + public long skip(final long n) throws IOException { return sourceStream.skip(n); } - /** Get available. - */ + /** + * Get available. + */ @Override - public int available() - throws IOException - { + public int available() throws IOException { return sourceStream.available(); } - /** Mark. - */ + /** + * Mark. + */ @Override - public void mark(final int readLimit) - { + public void mark(final int readLimit) { sourceStream.mark(readLimit); } - /** Reset. - */ + /** + * Reset. + */ @Override - public void reset() - throws IOException - { + public void reset() throws IOException { sourceStream.reset(); } - /** Check if mark is supported. - */ + /** + * Check if mark is supported. + */ @Override - public boolean markSupported() - { + public boolean markSupported() { return sourceStream.markSupported(); } - /** Close. - */ + /** + * Close. + */ @Override - public void close() - throws IOException - { + public void close() throws IOException { sourceStream.close(); } diff --git a/httpclient/src/test/java/org/apache/http/client/entity/TestDeflate.java b/httpclient/src/test/java/org/apache/http/client/entity/TestDeflate.java new file mode 100644 index 0000000000..6cded07b7e --- /dev/null +++ b/httpclient/src/test/java/org/apache/http/client/entity/TestDeflate.java @@ -0,0 +1,58 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.entity; + +import java.util.zip.Deflater; + +import org.apache.http.Consts; +import org.apache.http.HttpEntity; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.util.EntityUtils; +import org.junit.Assert; +import org.junit.Test; + +public class TestDeflate { + + @Test + public void testCompressDecompress() throws Exception { + + final String s = "some kind of text"; + final byte[] input = s.getBytes(Consts.ASCII); + + // Compress the bytes + final byte[] compressed = new byte[input.length * 2]; + final Deflater compresser = new Deflater(); + compresser.setInput(input); + compresser.finish(); + final int len = compresser.deflate(compressed); + + final HttpEntity entity = new DeflateDecompressingEntity(new ByteArrayEntity(compressed, 0, len)); + Assert.assertEquals(s, EntityUtils.toString(entity)); + } + +} diff --git a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java index 0145ef46ed..adc53403f4 100644 --- a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java +++ b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java @@ -29,15 +29,12 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; -import java.util.concurrent.atomic.AtomicBoolean; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; -import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; import org.junit.Assert; @@ -69,32 +66,6 @@ public void testCompressionDecompression() throws Exception { Assert.assertEquals("some kind of text", EntityUtils.toString(gunzipe, Consts.ASCII)); } - @Test - public void testGzipDecompressingEntityDoesNotCrashInConstructorAndLeaveInputStreamOpen() - throws Exception { - final AtomicBoolean inputStreamIsClosed = new AtomicBoolean(false); - final HttpEntity in = new InputStreamEntity(new InputStream() { - @Override - public int read() throws IOException { - throw new IOException("An exception occurred"); - } - - @Override - public void close() throws IOException { - inputStreamIsClosed.set(true); - } - - }, 123); - final GzipDecompressingEntity gunzipe = new GzipDecompressingEntity(in); - try { - gunzipe.getContent(); - } catch (final IOException e) { - // As I cannot get the content, GzipDecompressingEntity is supposed - // to have released everything - Assert.assertTrue(inputStreamIsClosed.get()); - } - } - @Test public void testCompressionIOExceptionLeavesOutputStreamOpen() throws Exception { final HttpEntity in = Mockito.mock(HttpEntity.class); From 79fdcb7dcbe957c0bcde2e0ea38714753b90dee1 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 14 Dec 2015 16:27:26 +0000 Subject: [PATCH 040/204] HTTPCLIENT-1704: IgnoreSpec#match to always return false git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1719950 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/impl/cookie/IgnoreSpec.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java index a6cd4f2e5f..71bf7902fe 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java @@ -55,6 +55,11 @@ public List parse(final Header header, final CookieOrigin origin) return Collections.emptyList(); } + @Override + public boolean match(final Cookie cookie, final CookieOrigin origin) { + return false; + } + @Override public List

formatCookies(final List cookies) { return Collections.emptyList(); From 148b7d5105a85f45cb207fdcb8e68a017167ff34 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 16 Dec 2015 16:19:13 +0000 Subject: [PATCH 041/204] Set socker buffer send/receive sizes from SocketConfig Contributed by Will Vuong git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1720386 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/conn/DefaultHttpClientConnectionOperator.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java index aef638c82d..582136408e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java @@ -28,9 +28,9 @@ import java.io.IOException; import java.net.ConnectException; -import java.net.NoRouteToHostException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.NoRouteToHostException; import java.net.Socket; import java.net.SocketTimeoutException; @@ -120,6 +120,13 @@ public void connect( sock.setReuseAddress(socketConfig.isSoReuseAddress()); sock.setTcpNoDelay(socketConfig.isTcpNoDelay()); sock.setKeepAlive(socketConfig.isSoKeepAlive()); + if (socketConfig.getRcvBufSize() > 0) { + sock.setReceiveBufferSize(socketConfig.getRcvBufSize()); + } + if (socketConfig.getSndBufSize() > 0) { + sock.setSendBufferSize(socketConfig.getSndBufSize()); + } + final int linger = socketConfig.getSoLinger(); if (linger >= 0) { sock.setSoLinger(true, linger); From da60349c5fb5cb30fc9bcedf7f0e651ea271e4e4 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 22 Dec 2015 12:36:10 +0000 Subject: [PATCH 042/204] Fix number or format arguments in OSGiProxyConfiguration The format string requires 6 arguments while 7 are provided. From the format string it is clear that the first argument has been added by mistake. Contributed by Michiel Eggermont git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1721386 13f79535-47bb-0310-9956-ffa450edef68 --- .../osgi/impl/OSGiProxyConfiguration.java | 3 +- .../osgi/impl/OSGiProxyConfigurationTest.java | 61 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java index 3a0516014c..00ae3a0be8 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java @@ -27,6 +27,7 @@ package org.apache.http.osgi.impl; import static java.lang.String.format; +import static java.util.Arrays.asList; import static org.apache.http.osgi.impl.PropertiesUtils.to; import java.util.Dictionary; @@ -135,7 +136,7 @@ public void update(final Dictionary config) { @Override public String toString() { return format("ProxyConfiguration [enabled=%s, hostname=%s, port=%s, username=%s, password=%s, proxyExceptions=%s]", - proxyExceptions, enabled, hostname, port, username, password, proxyExceptions); + enabled, hostname, port, username, password, asList(proxyExceptions)); } } diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java new file mode 100644 index 0000000000..55b117497a --- /dev/null +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java @@ -0,0 +1,61 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import org.junit.Test; + +import java.util.Dictionary; +import java.util.Hashtable; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +public class OSGiProxyConfigurationTest { + + @Test + public void testToString() { + + final Dictionary config = new Hashtable(); + config.put("proxy.enabled", false); + config.put("proxy.host", "h"); + config.put("proxy.port", 1); + config.put("proxy.username", "u"); + config.put("proxy.password", "p"); + config.put("proxy.exceptions", new String[]{"e"}); + + final OSGiProxyConfiguration configuration = new OSGiProxyConfiguration(); + configuration.update(config); + + final String string = configuration.toString(); + assertThat(string, containsString("enabled=false")); + assertThat(string, containsString("hostname=h")); + assertThat(string, containsString("port=1")); + assertThat(string, containsString("username=u")); + assertThat(string, containsString("password=p")); + assertThat(string, containsString("proxyExceptions=[e]")); + } +} From 6c46f1952ba9221acc22e420960455489b2273ab Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 2 Jan 2016 14:15:43 +0000 Subject: [PATCH 043/204] HTTPCLIENT-1710 - fixes - examine all exceptions, correct capture groups count Contributed by 212427891 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1722632 13f79535-47bb-0310-9956-ffa450edef68 --- httpclient-osgi/pom.xml | 5 + .../http/osgi/impl/OSGiHttpRoutePlanner.java | 11 +- .../osgi/impl/TestOSGiHttpRoutePlanner.java | 160 ++++++++++++++++++ 3 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index e403f58108..b6956cc7cb 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -98,6 +98,11 @@ junit test + + org.mockito + mockito-core + test + diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java index 2f0fe5f1be..c422e39f48 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java @@ -73,7 +73,7 @@ public OSGiHttpRoutePlanner( @Override protected HttpHost determineProxy(final HttpHost target, final HttpRequest request, final HttpContext context) throws HttpException { ProxyConfiguration proxyConfiguration = null; - + HttpHost proxyHost = null; for (final ServiceRegistration registration : registeredConfigurations.values()) { final Object proxyConfigurationObject = bundleContext.getService(registration.getReference()); if (proxyConfigurationObject != null) { @@ -82,15 +82,16 @@ protected HttpHost determineProxy(final HttpHost target, final HttpRequest reque for (final String exception : proxyConfiguration.getProxyExceptions()) { if (createMatcher(exception).matches(target.getHostName())) { return null; - } else { - return new HttpHost(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); } } + if (null == proxyHost) { + proxyHost = new HttpHost(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); + } } } } - return null; + return proxyHost; } private static HostMatcher createMatcher(final String name) { @@ -174,7 +175,7 @@ static NetworkAddress parse(final String adrSpec) { final int i4 = toInt(nameMatcher.group(4), 255); final int ip = i1 << 24 | i2 << 16 | i3 << 8 | i4; - int mask = toInt(nameMatcher.group(6), 32); + int mask = toInt(nameMatcher.group(4), 32); mask = (mask == 32) ? -1 : -1 - (-1 >>> mask); return new NetworkAddress(ip, mask); diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java new file mode 100644 index 0000000000..0b7bc29799 --- /dev/null +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java @@ -0,0 +1,160 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetAddress; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.http.HttpHost; +import org.apache.http.osgi.services.ProxyConfiguration; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; + + +/** + * @since 4.4.3 + */ + +public class TestOSGiHttpRoutePlanner { + + final ProxyConfiguration pc1 = new ProxyConfiguration() { + @Override + public boolean isEnabled() {return true; } + @Override + public String getHostname() {return "proxy1"; } + @Override + public int getPort() { return 8080; } + @Override + public String getUsername() { return ""; } + @Override + public String getPassword() {return ""; } + @Override + public String[] getProxyExceptions() { return new String[]{"localhost", "127.0.0.1", ".apache.org"}; } + }; + + final ProxyConfiguration pc2 = new ProxyConfiguration() { + @Override + public boolean isEnabled() {return true; } + @Override + public String getHostname() {return "proxy2"; } + @Override + public int getPort() { return 9090; } + @Override + public String getUsername() { return ""; } + @Override + public String getPassword() {return ""; } + @Override + public String[] getProxyExceptions() { return new String[]{"localhost", "127.0.0.1", ".oracle.com", "12.34.34.8"}; } + }; + + @Test + public void testDeterminProxy() throws Exception { + final ServiceReference sRef1 = mock(ServiceReference.class); + final ServiceRegistration sReg1 = mock(ServiceRegistration.class); + when(sReg1.getReference()).thenReturn(sRef1); + final BundleContext bc = mock(BundleContext.class); + when(bc.getService(sRef1)).thenReturn(this.pc1); + + final Map registrations = new TreeMap(); // TreeMap for order + registrations.put("foo1", sReg1); + + OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations); + + HttpHost proxy = planner.determineProxy(new HttpHost("localhost", 8090), null, null); + assertNull(proxy); + + proxy = planner.determineProxy(new HttpHost("there", 9090), null, null); + assertNotNull(proxy); + assertTrue(proxy.getHostName().equals("proxy1")); + + proxy = planner.determineProxy(new HttpHost("10.2.144.23", 4554), null, null); + assertNotNull(proxy); + assertTrue(proxy.getHostName().equals("proxy1")); + + final InetAddress addr = InetAddress.getByName("localhost"); + proxy = planner.determineProxy(new HttpHost(addr, 4554), null, null); + assertNull(proxy); + + proxy = planner.determineProxy(new HttpHost("hc.apache.org", 4554), null, null); + assertNull(proxy); + + + // test with more than one registration of proxyConfiguration + final ServiceReference sRef2 = mock(ServiceReference.class); + final ServiceRegistration sReg2 = mock(ServiceRegistration.class); + when(sReg2.getReference()).thenReturn(sRef2); + when(bc.getService(sRef2)).thenReturn(this.pc2); + registrations.put("foo2", sReg2); + + planner = new OSGiHttpRoutePlanner(bc, registrations); + proxy = planner.determineProxy(new HttpHost("localhost", 8090), null, null); + assertNull(proxy); + + proxy = planner.determineProxy(new HttpHost("there", 9090), null, null); + assertNotNull(proxy); + assertTrue(proxy.getHostName().equals("proxy1")); // the first one + + proxy = planner.determineProxy(new HttpHost(addr, 4554), null, null); + assertNull(proxy); + + proxy = planner.determineProxy(new HttpHost("hc.apache.org", 4554), null, null); + assertNull(proxy); + + proxy = planner.determineProxy(new HttpHost("docs.oracle.com", 4554), null, null); + assertNull(proxy); + } + + @Test + public void testMasking() throws Exception { + final ServiceReference sRef2 = mock(ServiceReference.class); + final ServiceRegistration sReg2 = mock(ServiceRegistration.class); + when(sReg2.getReference()).thenReturn(sRef2); + final BundleContext bc = mock(BundleContext.class); + when(bc.getService(sRef2)).thenReturn(this.pc2); + final Map registrations = new TreeMap(); + registrations.put("foo2", sReg2); + + final OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations); + + HttpHost proxy = planner.determineProxy(new HttpHost("12.34.34.2", 4554), null, null); + assertNotNull(proxy); + assertTrue(proxy.getHostName().equals("proxy2")); + + proxy = planner.determineProxy(new HttpHost("12.34.34.8", 4554), null, null); + assertNotNull(proxy); + } + +} From f9514a0f9ac6c43e2fae78586e751dabb69d07f7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 4 Jan 2016 19:55:16 +0000 Subject: [PATCH 044/204] Fix for HTTPCORE-397 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1722952 13f79535-47bb-0310-9956-ffa450edef68 --- .../DefaultClientConnectionReuseStrategy.java | 65 +++++++++++++++++++ .../http/impl/client/HttpClientBuilder.java | 5 +- 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 httpclient/src/main/java/org/apache/http/impl/client/DefaultClientConnectionReuseStrategy.java diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultClientConnectionReuseStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultClientConnectionReuseStrategy.java new file mode 100644 index 0000000000..3fae878a39 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultClientConnectionReuseStrategy.java @@ -0,0 +1,65 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.client; + +import org.apache.http.Header; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.TokenIterator; +import org.apache.http.impl.DefaultConnectionReuseStrategy; +import org.apache.http.message.BasicHeaderIterator; +import org.apache.http.message.BasicTokenIterator; +import org.apache.http.protocol.HTTP; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpCoreContext; + +public class DefaultClientConnectionReuseStrategy extends DefaultConnectionReuseStrategy { + + public static final DefaultClientConnectionReuseStrategy INSTANCE = new DefaultClientConnectionReuseStrategy(); + + @Override + public boolean keepAlive(final HttpResponse response, final HttpContext context) { + + final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST); + if (request != null) { + final Header[] connHeaders = request.getHeaders(HttpHeaders.CONNECTION); + if (connHeaders.length != 0) { + final TokenIterator ti = new BasicTokenIterator(new BasicHeaderIterator(connHeaders, null)); + while (ti.hasNext()) { + final String token = ti.nextToken(); + if (HTTP.CONN_CLOSE.equalsIgnoreCase(token)) { + return false; + } + } + } + } + return super.keepAlive(response, context); + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index caef84d65e..9cf34397d1 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -86,7 +86,6 @@ import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.conn.util.PublicSuffixMatcherLoader; import org.apache.http.cookie.CookieSpecProvider; -import org.apache.http.impl.DefaultConnectionReuseStrategy; import org.apache.http.impl.NoConnectionReuseStrategy; import org.apache.http.impl.auth.BasicSchemeFactory; import org.apache.http.impl.auth.DigestSchemeFactory; @@ -997,12 +996,12 @@ public CloseableHttpClient build() { if (systemProperties) { final String s = System.getProperty("http.keepAlive", "true"); if ("true".equalsIgnoreCase(s)) { - reuseStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE; + reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE; } else { reuseStrategyCopy = NoConnectionReuseStrategy.INSTANCE; } } else { - reuseStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE; + reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE; } } ConnectionKeepAliveStrategy keepAliveStrategyCopy = this.keepAliveStrategy; From b781fa8e0382af8b53aa06e52cb003ff3823f2de Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 4 Jan 2016 20:22:48 +0000 Subject: [PATCH 045/204] HTTPCLIENT-1700: Netscape draft, browser compatibility, RFC 2109, RFC 2965 and default cookie specs to ignore cookies with empty name for consistency with RFC 6265 specs git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1722959 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/impl/cookie/CookieSpecBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java b/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java index 32730d25b8..f4f98f1916 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java @@ -92,7 +92,7 @@ protected List parse(final HeaderElement[] elems, final CookieOrigin ori final String name = headerelement.getName(); final String value = headerelement.getValue(); if (name == null || name.isEmpty()) { - throw new MalformedCookieException("Cookie name may not be empty"); + continue; } final BasicClientCookie cookie = new BasicClientCookie(name, value); From 1d50c1a1a16ee6f9c5930d966f1b234d98bf261f Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 15 Jan 2016 16:38:07 +0000 Subject: [PATCH 046/204] HTTPCLIENT-1712: SPNego schemes to take service scheme into account when generating auth token Contributed by Georg Romstorfer git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1724852 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/impl/auth/GGSSchemeBase.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java index eba45c2141..502be3cb0b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java @@ -28,6 +28,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.Locale; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; @@ -79,6 +80,7 @@ enum State { /** base64 decoded challenge **/ private byte[] token; + private String service; GGSSchemeBase(final boolean stripPort, final boolean useCanonicalHostname) { super(); @@ -116,7 +118,7 @@ protected byte[] generateGSSToken( inputBuff = new byte[0]; } final GSSManager manager = getManager(); - final GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE); + final GSSName serverName = manager.createName(service + "@" + authServer, GSSName.NT_HOSTBASED_SERVICE); final GSSCredential gssCredential; if (credentials instanceof KerberosCredentials) { @@ -212,6 +214,8 @@ public Header authenticate( authServer = hostname + ":" + host.getPort(); } + service = host.getSchemeName().toUpperCase(Locale.ROOT); + if (log.isDebugEnabled()) { log.debug("init " + authServer); } From 3a9a452730bec25b97e805d7a56bf493c89cbaf7 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 26 Jan 2016 05:12:27 +0000 Subject: [PATCH 047/204] [HTTPCLIENT-1714] Add HttpClientBuilder.setDnsResolver(DnsResolver). git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1726729 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 15 +++++++++++++++ .../http/impl/client/HttpClientBuilder.java | 14 +++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 32c1c9691e..08c2a39006 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,18 @@ +Release 4.5.2 +------------------- + +HttpClient 4.5.2 (GA) is a maintenance release that fixes a number of minor defects found since 4.5.1. + +Please note that as of 4.4 HttpClient requires Java 1.6 or newer. + +Changelog: +------------------- + +* [HTTPCLIENT-1714] Add HttpClientBuilder.setDnsResolver(DnsResolver). + Contributed by Alexis Thaveau + + + Release 4.5.1 ------------------- diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 9cf34397d1..943848cb6e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -74,6 +74,7 @@ import org.apache.http.config.RegistryBuilder; import org.apache.http.config.SocketConfig; import org.apache.http.conn.ConnectionKeepAliveStrategy; +import org.apache.http.conn.DnsResolver; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.SchemePortResolver; import org.apache.http.conn.routing.HttpRoutePlanner; @@ -168,6 +169,7 @@ public class HttpClientBuilder { private AuthenticationStrategy proxyAuthStrategy; private UserTokenHandler userTokenHandler; private HttpProcessor httpprocessor; + private DnsResolver dnsResolver; private LinkedList requestFirst; private LinkedList requestLast; @@ -610,6 +612,16 @@ public final HttpClientBuilder setHttpProcessor(final HttpProcessor httpprocesso return this; } + /** + * Assigns {@link DnsResolver} instance. + *

+ * Please note this value can be overridden by the {@link #setConnectionManager(HttpClientConnectionManager)} method. + */ + public final HttpClientBuilder setDnsResolver(final DnsResolver dnsResolver) { + this.dnsResolver = dnsResolver; + return this; + } + /** * Assigns {@link HttpRequestRetryHandler} instance. *

@@ -965,7 +977,7 @@ public CloseableHttpClient build() { .build(), null, null, - null, + dnsResolver, connTimeToLive, connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS); if (defaultSocketConfig != null) { From 517e64778f36d0a251ad93a9e09d9fc1def52762 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 27 Jan 2016 08:34:23 +0000 Subject: [PATCH 048/204] [HTTPCLIENT-1715] NTLMEngineImpl.Type1Message not thread safe but declared as a constant. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1726957 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 2 ++ .../main/java/org/apache/http/impl/auth/NTLMEngineImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 08c2a39006..30cc6af3dc 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -11,6 +11,8 @@ Changelog: * [HTTPCLIENT-1714] Add HttpClientBuilder.setDnsResolver(DnsResolver). Contributed by Alexis Thaveau +* [HTTPCLIENT-1715] NTLMEngineImpl.Type1Message not thread safe but declared as a constant. + Contributed by Olivier Lafontaine , Gary Gregory Release 4.5.1 diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 0926e2c095..890f6474c9 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -98,7 +98,7 @@ final class NTLMEngineImpl implements NTLMEngine { SIGNATURE[bytesWithoutNull.length] = (byte) 0x00; } - private static final Type1Message TYPE_1_MESSAGE = new Type1Message(); + private static final String TYPE_1_MESSAGE = new Type1Message().getResponse(); /** * Returns the response for the given message. @@ -145,7 +145,7 @@ static String getResponseFor(final String message, final String username, final static String getType1Message(final String host, final String domain) throws NTLMEngineException { // For compatibility reason do not include domain and host in type 1 message //return new Type1Message(domain, host).getResponse(); - return TYPE_1_MESSAGE.getResponse(); + return TYPE_1_MESSAGE; } /** From fb27bd73534952df3ef44d85d23b999ae6994311 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 27 Jan 2016 08:43:17 +0000 Subject: [PATCH 049/204] Add missing @Deprecated annotations. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1726958 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/impl/cookie/BrowserCompatSpec.java | 1 + .../http/impl/cookie/BrowserCompatVersionAttributeHandler.java | 1 + httpclient/src/main/java/org/apache/http/auth/NTCredentials.java | 1 + .../java/org/apache/http/auth/UsernamePasswordCredentials.java | 1 + 4 files changed, 4 insertions(+) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java index 7b20123361..46d834d5e0 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java @@ -60,6 +60,7 @@ * * @since 4.0 */ +@Deprecated @ThreadSafe public class BrowserCompatSpec extends CookieSpecBase { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java index c4c389faa8..387259ca8b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java @@ -41,6 +41,7 @@ * * @since 4.3 */ +@Deprecated @Immutable public class BrowserCompatVersionAttributeHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { diff --git a/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java b/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java index 3ce343fb3c..430eb2d0b1 100644 --- a/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java @@ -61,6 +61,7 @@ public class NTCredentials implements Credentials, Serializable { * @param usernamePassword the domain/username:password formed string * @deprecated (4.5) will be replaced with {@code String}, {@code char[]} in 5.0 */ + @Deprecated public NTCredentials(final String usernamePassword) { super(); Args.notNull(usernamePassword, "Username:password string"); diff --git a/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java b/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java index e31d036f3c..b593b2472d 100644 --- a/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java @@ -54,6 +54,7 @@ public class UsernamePasswordCredentials implements Credentials, Serializable { * @see #toString * @deprecated (4.5) will be replaced with {@code String}, {@code char[]} in 5.0 */ + @Deprecated public UsernamePasswordCredentials(final String usernamePassword) { super(); Args.notNull(usernamePassword, "Username:password string"); From 8a27962f79713a240cb4596ae93e62e3f3f80dc4 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 27 Jan 2016 08:51:00 +0000 Subject: [PATCH 050/204] Add missing @Override annotations. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1726962 13f79535-47bb-0310-9956-ffa450edef68 --- .../auth/win/TestWindowsNegotiateScheme.java | 1 + .../protocol/RequestProxyAuthentication.java | 1 + .../protocol/RequestTargetAuthentication.java | 1 + .../client/protocol/ResponseAuthCache.java | 1 + .../http/conn/BasicEofSensorWatcher.java | 3 ++ .../apache/http/conn/BasicManagedEntity.java | 5 +++ .../conn/MultihomePlainSocketFactory.java | 3 ++ .../http/conn/params/ConnManagerParams.java | 1 + .../http/conn/params/ConnPerRouteBean.java | 1 + .../http/conn/scheme/PlainSocketFactory.java | 5 +++ .../http/conn/ssl/SSLSocketFactory.java | 11 ++++++ .../http/impl/auth/NegotiateScheme.java | 4 +++ .../impl/auth/NegotiateSchemeFactory.java | 1 + .../client/AbstractAuthenticationHandler.java | 1 + .../http/impl/client/AbstractHttpClient.java | 3 ++ .../client/AuthenticationStrategyAdaptor.java | 5 +++ .../http/impl/client/AutoRetryHttpClient.java | 10 ++++++ .../http/impl/client/ClientParamsStack.java | 4 +++ .../impl/client/DecompressingHttpClient.java | 10 ++++++ .../DefaultProxyAuthenticationHandler.java | 2 ++ .../impl/client/DefaultRedirectHandler.java | 2 ++ .../DefaultRedirectStrategyAdaptor.java | 2 ++ .../impl/client/DefaultRequestDirector.java | 1 + .../DefaultTargetAuthenticationHandler.java | 2 ++ .../impl/conn/AbstractClientConnAdapter.java | 28 +++++++++++++++ .../impl/conn/AbstractPooledConnAdapter.java | 10 ++++++ .../conn/BasicClientConnectionManager.java | 8 +++++ .../impl/conn/DefaultClientConnection.java | 11 ++++++ .../conn/DefaultClientConnectionOperator.java | 3 ++ .../impl/conn/DefaultHttpRoutePlanner.java | 1 + .../apache/http/impl/conn/HttpConnPool.java | 1 + .../impl/conn/LoggingSessionInputBuffer.java | 8 +++++ .../impl/conn/LoggingSessionOutputBuffer.java | 7 ++++ .../conn/ManagedClientConnectionImpl.java | 35 +++++++++++++++++++ .../conn/PoolingClientConnectionManager.java | 16 +++++++++ .../impl/conn/ProxySelectorRoutePlanner.java | 1 + .../impl/conn/SingleClientConnManager.java | 8 +++++ .../http/impl/conn/tsccm/ConnPoolByRoute.java | 2 ++ .../impl/conn/tsccm/RouteSpecificPool.java | 1 + .../tsccm/ThreadSafeClientConnManager.java | 8 +++++ .../apache/http/auth/KerberosCredentials.java | 2 ++ .../http/conn/ssl/AbstractVerifier.java | 1 + .../http/entity/mime/MultipartEntity.java | 9 +++++ 43 files changed, 240 insertions(+) diff --git a/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java b/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java index 1fea3f835f..dd7275a835 100644 --- a/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java +++ b/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java @@ -100,6 +100,7 @@ public void testNoInfiniteLoopOnSPNOutsideDomain() throws Exception { final Registry authSchemeRegistry = RegistryBuilder.create() .register(AuthSchemes.SPNEGO, new AuthSchemeProvider() { + @Override public AuthScheme create(final HttpContext context) { return new WindowsNegotiateSchemeGetTokenFail(AuthSchemes.SPNEGO, "HTTP/example.com"); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java index 686d86983c..b5ef5ad647 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java @@ -56,6 +56,7 @@ public RequestProxyAuthentication() { super(); } + @Override public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { Args.notNull(request, "HTTP request"); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java index 30d1a89eac..263ff57079 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java @@ -53,6 +53,7 @@ public RequestTargetAuthentication() { super(); } + @Override public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { Args.notNull(request, "HTTP request"); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java index a08f1827f9..23322e8a8a 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java @@ -67,6 +67,7 @@ public ResponseAuthCache() { super(); } + @Override public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException { Args.notNull(response, "HTTP request"); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java index b84602e4e8..9fa2c331c1 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java @@ -63,6 +63,7 @@ public BasicEofSensorWatcher(final ManagedClientConnection conn, attemptReuse = reuse; } + @Override public boolean eofDetected(final InputStream wrapped) throws IOException { @@ -79,6 +80,7 @@ public boolean eofDetected(final InputStream wrapped) return false; } + @Override public boolean streamClosed(final InputStream wrapped) throws IOException { @@ -95,6 +97,7 @@ public boolean streamClosed(final InputStream wrapped) return false; } + @Override public boolean streamAbort(final InputStream wrapped) throws IOException { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java index ecd4f6baa2..24dca916b1 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java @@ -120,10 +120,12 @@ public void writeTo(final OutputStream outstream) throws IOException { ensureConsumed(); } + @Override public void releaseConnection() throws IOException { ensureConsumed(); } + @Override public void abortConnection() throws IOException { if (managedConn != null) { @@ -135,6 +137,7 @@ public void abortConnection() throws IOException { } } + @Override public boolean eofDetected(final InputStream wrapped) throws IOException { try { if (managedConn != null) { @@ -153,6 +156,7 @@ public boolean eofDetected(final InputStream wrapped) throws IOException { return false; } + @Override public boolean streamClosed(final InputStream wrapped) throws IOException { try { if (managedConn != null) { @@ -178,6 +182,7 @@ public boolean streamClosed(final InputStream wrapped) throws IOException { return false; } + @Override public boolean streamAbort(final InputStream wrapped) throws IOException { if (managedConn != null) { managedConn.abortConnection(); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java index 01e465d5d2..7ce6e05002 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java @@ -83,6 +83,7 @@ private MultihomePlainSocketFactory() { // non-javadoc, see interface org.apache.http.conn.SocketFactory + @Override public Socket createSocket() { return new Socket(); } @@ -102,6 +103,7 @@ public Socket createSocket() { * @throws IOException if an error occurs during the connection * @throws SocketTimeoutException if timeout expires before connecting */ + @Override public Socket connectSocket(final Socket socket, final String host, final int port, final InetAddress localAddress, final int localPort, final HttpParams params) @@ -159,6 +161,7 @@ public Socket connectSocket(final Socket socket, final String host, final int po * * @throws IllegalArgumentException if the argument is invalid */ + @Override public final boolean isSecure(final Socket sock) throws IllegalArgumentException { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java index ff6af4e0a6..3c4ddfb87b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java @@ -83,6 +83,7 @@ public static void setTimeout(final HttpParams params, final long timeout) { /** The default maximum number of connections allowed per host */ private static final ConnPerRoute DEFAULT_CONN_PER_ROUTE = new ConnPerRoute() { + @Override public int getMaxForRoute(final HttpRoute route) { return ConnPerRouteBean.DEFAULT_MAX_CONNECTIONS_PER_ROUTE; } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java index 6700c5b919..241424f5b7 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java @@ -86,6 +86,7 @@ public void setMaxForRoute(final HttpRoute route, final int max) { this.maxPerHostMap.put(route, Integer.valueOf(max)); } + @Override public int getMaxForRoute(final HttpRoute route) { Args.notNull(route, "HTTP route"); final Integer max = this.maxPerHostMap.get(route); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java index 7a59cea88f..a6973b1690 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java @@ -83,10 +83,12 @@ public PlainSocketFactory() { * * @since 4.1 */ + @Override public Socket createSocket(final HttpParams params) { return new Socket(); } + @Override public Socket createSocket() { return new Socket(); } @@ -94,6 +96,7 @@ public Socket createSocket() { /** * @since 4.1 */ + @Override public Socket connectSocket( final Socket socket, final InetSocketAddress remoteAddress, @@ -130,6 +133,7 @@ public Socket connectSocket( * * @return {@code false} */ + @Override public final boolean isSecure(final Socket sock) { return false; } @@ -137,6 +141,7 @@ public final boolean isSecure(final Socket sock) { /** * @deprecated (4.1) Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)} */ + @Override @Deprecated public Socket connectSocket( final Socket socket, diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java index 3c905774de..37f539c541 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java @@ -379,10 +379,12 @@ public SSLSocketFactory( * This method will create a unconnected instance of {@link Socket} class. * @since 4.1 */ + @Override public Socket createSocket(final HttpParams params) throws IOException { return createSocket((HttpContext) null); } + @Override public Socket createSocket() throws IOException { return createSocket((HttpContext) null); } @@ -390,6 +392,7 @@ public Socket createSocket() throws IOException { /** * @since 4.1 */ + @Override public Socket connectSocket( final Socket socket, final InetSocketAddress remoteAddress, @@ -424,6 +427,7 @@ public Socket connectSocket( * * @throws IllegalArgumentException if the argument is invalid */ + @Override public boolean isSecure(final Socket sock) throws IllegalArgumentException { Args.notNull(sock, "Socket"); Asserts.check(sock instanceof SSLSocket, "Socket not created by this factory"); @@ -434,6 +438,7 @@ public boolean isSecure(final Socket sock) throws IllegalArgumentException { /** * @since 4.2 */ + @Override public Socket createLayeredSocket( final Socket socket, final String host, @@ -442,6 +447,7 @@ public Socket createLayeredSocket( return createLayeredSocket(socket, host, port, (HttpContext) null); } + @Override public Socket createLayeredSocket( final Socket socket, final String host, @@ -459,6 +465,7 @@ public X509HostnameVerifier getHostnameVerifier() { return this.hostnameVerifier; } + @Override public Socket connectSocket( final Socket socket, final String host, final int port, @@ -479,6 +486,7 @@ public Socket connectSocket( return connectSocket(socket, remoteAddress, localAddress, params); } + @Override public Socket createSocket( final Socket socket, final String host, final int port, @@ -509,12 +517,14 @@ private void internalPrepareSocket(final SSLSocket socket) throws IOException { prepareSocket(socket); } + @Override public Socket createSocket(final HttpContext context) throws IOException { final SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); internalPrepareSocket(sock); return sock; } + @Override public Socket connectSocket( final int connectTimeout, final Socket socket, @@ -548,6 +558,7 @@ public Socket connectSocket( } } + @Override public Socket createLayeredSocket( final Socket socket, final String target, diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateScheme.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateScheme.java index d39a0193c4..60a5490396 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateScheme.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateScheme.java @@ -79,6 +79,7 @@ public NegotiateScheme() { * * @return {@code Negotiate} */ + @Override public String getSchemeName() { return "Negotiate"; } @@ -181,6 +182,7 @@ protected byte[] generateToken(final byte[] input, final String authServer, fina * * @return the parameter with the given name */ + @Override public String getParameter(final String name) { Args.notNull(name, "Parameter name"); return null; @@ -192,6 +194,7 @@ public String getParameter(final String name) { * * @return {@code null} */ + @Override public String getRealm() { return null; } @@ -202,6 +205,7 @@ public String getRealm() { * * @return {@code true}. */ + @Override public boolean isConnectionBased() { return true; } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateSchemeFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateSchemeFactory.java index c943bc5419..12217a59cd 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateSchemeFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/NegotiateSchemeFactory.java @@ -58,6 +58,7 @@ public NegotiateSchemeFactory() { this(null, false); } + @Override public AuthScheme newInstance(final HttpParams params) { return new NegotiateScheme(this.spengoGenerator, this.stripPort); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java index 9f211a407f..c3af00dff2 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java @@ -135,6 +135,7 @@ protected List getAuthPreferences( return getAuthPreferences(); } + @Override public AuthScheme selectScheme( final Map challenges, final HttpResponse response, diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java index a1f734579b..18a42d727d 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java @@ -461,6 +461,7 @@ protected UserTokenHandler createUserTokenHandler() { } // non-javadoc, see interface HttpClient + @Override public synchronized final HttpParams getParams() { if (defaultParams == null) { defaultParams = createHttpParams(); @@ -479,6 +480,7 @@ public synchronized void setParams(final HttpParams params) { } + @Override public synchronized final ClientConnectionManager getConnectionManager() { if (connManager == null) { connManager = createClientConnectionManager(); @@ -1007,6 +1009,7 @@ protected HttpParams determineParams(final HttpRequest req) { } + @Override public void close() { getConnectionManager().shutdown(); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java index 3f5106f331..2ff4ccf4d7 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java @@ -69,6 +69,7 @@ public AuthenticationStrategyAdaptor(final AuthenticationHandler handler) { this.handler = handler; } + @Override public boolean isAuthenticationRequested( final HttpHost authhost, final HttpResponse response, @@ -76,6 +77,7 @@ public boolean isAuthenticationRequested( return this.handler.isAuthenticationRequested(response, context); } + @Override public Map getChallenges( final HttpHost authhost, final HttpResponse response, @@ -83,6 +85,7 @@ public Map getChallenges( return this.handler.getChallenges(response, context); } + @Override public Queue select( final Map challenges, final HttpHost authhost, @@ -127,6 +130,7 @@ public Queue select( return options; } + @Override public void authSucceeded( final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) { AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE); @@ -143,6 +147,7 @@ public void authSucceeded( } } + @Override public void authFailed( final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) { final AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java index b24d424da7..272872a67b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java @@ -107,17 +107,20 @@ public AutoRetryHttpClient(final HttpClient client) { this(client, new DefaultServiceUnavailableRetryStrategy()); } + @Override public HttpResponse execute(final HttpHost target, final HttpRequest request) throws IOException { final HttpContext defaultContext = null; return execute(target, request, defaultContext); } + @Override public T execute(final HttpHost target, final HttpRequest request, final ResponseHandler responseHandler) throws IOException { return execute(target, request, responseHandler, null); } + @Override public T execute(final HttpHost target, final HttpRequest request, final ResponseHandler responseHandler, final HttpContext context) throws IOException { @@ -125,11 +128,13 @@ public T execute(final HttpHost target, final HttpRequest request, return responseHandler.handleResponse(resp); } + @Override public HttpResponse execute(final HttpUriRequest request) throws IOException { final HttpContext context = null; return execute(request, context); } + @Override public HttpResponse execute(final HttpUriRequest request, final HttpContext context) throws IOException { final URI uri = request.getURI(); @@ -138,11 +143,13 @@ public HttpResponse execute(final HttpUriRequest request, final HttpContext cont return execute(httpHost, request, context); } + @Override public T execute(final HttpUriRequest request, final ResponseHandler responseHandler) throws IOException { return execute(request, responseHandler, null); } + @Override public T execute(final HttpUriRequest request, final ResponseHandler responseHandler, final HttpContext context) throws IOException { @@ -150,6 +157,7 @@ public T execute(final HttpUriRequest request, return responseHandler.handleResponse(resp); } + @Override public HttpResponse execute(final HttpHost target, final HttpRequest request, final HttpContext context) throws IOException { for (int c = 1;; c++) { @@ -179,10 +187,12 @@ public HttpResponse execute(final HttpHost target, final HttpRequest request, } } + @Override public ClientConnectionManager getConnectionManager() { return backend.getConnectionManager(); } + @Override public HttpParams getParams() { return backend.getParams(); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java index a7da9b8abf..65f80d25a7 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java @@ -189,6 +189,7 @@ public final HttpParams getOverrideParams() { * @return the highest-priority value for that parameter, or * {@code null} if it is not set anywhere in this stack */ + @Override public Object getParameter(final String name) { Args.notNull(name, "Parameter name"); @@ -222,6 +223,7 @@ public Object getParameter(final String name) { * * @throws UnsupportedOperationException always */ + @Override public HttpParams setParameter(final String name, final Object value) throws UnsupportedOperationException { @@ -242,6 +244,7 @@ public HttpParams setParameter(final String name, final Object value) * * @throws UnsupportedOperationException always */ + @Override public boolean removeParameter(final String name) { throw new UnsupportedOperationException ("Removing parameters in a stack is not supported."); @@ -262,6 +265,7 @@ public boolean removeParameter(final String name) { * * @return {@code this} parameter stack */ + @Override public HttpParams copy() { return this; } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DecompressingHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DecompressingHttpClient.java index db2255e8be..0f8572f2ff 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DecompressingHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DecompressingHttpClient.java @@ -107,14 +107,17 @@ public DecompressingHttpClient(final HttpClient backend) { this.contentEncodingInterceptor = responseInterceptor; } + @Override public HttpParams getParams() { return backend.getParams(); } + @Override public ClientConnectionManager getConnectionManager() { return backend.getConnectionManager(); } + @Override public HttpResponse execute(final HttpUriRequest request) throws IOException, ClientProtocolException { return execute(getHttpHost(request), request, (HttpContext)null); @@ -134,16 +137,19 @@ HttpHost getHttpHost(final HttpUriRequest request) { return URIUtils.extractHost(uri); } + @Override public HttpResponse execute(final HttpUriRequest request, final HttpContext context) throws IOException, ClientProtocolException { return execute(getHttpHost(request), request, context); } + @Override public HttpResponse execute(final HttpHost target, final HttpRequest request) throws IOException, ClientProtocolException { return execute(target, request, (HttpContext)null); } + @Override public HttpResponse execute(final HttpHost target, final HttpRequest request, final HttpContext context) throws IOException, ClientProtocolException { try { @@ -179,24 +185,28 @@ public HttpResponse execute(final HttpHost target, final HttpRequest request, } } + @Override public T execute(final HttpUriRequest request, final ResponseHandler responseHandler) throws IOException, ClientProtocolException { return execute(getHttpHost(request), request, responseHandler); } + @Override public T execute(final HttpUriRequest request, final ResponseHandler responseHandler, final HttpContext context) throws IOException, ClientProtocolException { return execute(getHttpHost(request), request, responseHandler, context); } + @Override public T execute(final HttpHost target, final HttpRequest request, final ResponseHandler responseHandler) throws IOException, ClientProtocolException { return execute(target, request, responseHandler, null); } + @Override public T execute(final HttpHost target, final HttpRequest request, final ResponseHandler responseHandler, final HttpContext context) throws IOException, ClientProtocolException { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java index 12f52fae20..14ce013e1e 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java @@ -56,6 +56,7 @@ public DefaultProxyAuthenticationHandler() { super(); } + @Override public boolean isAuthenticationRequested( final HttpResponse response, final HttpContext context) { @@ -64,6 +65,7 @@ public boolean isAuthenticationRequested( return status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED; } + @Override public Map getChallenges( final HttpResponse response, final HttpContext context) throws MalformedChallengeException { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java index 6794d27265..228b69096d 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java @@ -70,6 +70,7 @@ public DefaultRedirectHandler() { super(); } + @Override public boolean isRedirectRequested( final HttpResponse response, final HttpContext context) { @@ -92,6 +93,7 @@ public boolean isRedirectRequested( } //end of switch } + @Override public URI getLocationURI( final HttpResponse response, final HttpContext context) throws ProtocolException { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java index aeb05eb69f..d87090fc33 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java @@ -54,6 +54,7 @@ public DefaultRedirectStrategyAdaptor(final RedirectHandler handler) { this.handler = handler; } + @Override public boolean isRedirected( final HttpRequest request, final HttpResponse response, @@ -61,6 +62,7 @@ public boolean isRedirected( return this.handler.isRedirectRequested(response, context); } + @Override public HttpUriRequest getRedirect( final HttpRequest request, final HttpResponse response, diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java index 1ee69a5815..ed233b2931 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java @@ -366,6 +366,7 @@ protected void rewriteRequestURI( // non-javadoc, see interface ClientRequestDirector + @Override public HttpResponse execute(final HttpHost targetHost, final HttpRequest request, final HttpContext context) throws HttpException, IOException { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java index 52f1303a45..c47f9e0849 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java @@ -56,6 +56,7 @@ public DefaultTargetAuthenticationHandler() { super(); } + @Override public boolean isAuthenticationRequested( final HttpResponse response, final HttpContext context) { @@ -64,6 +65,7 @@ public boolean isAuthenticationRequested( return status == HttpStatus.SC_UNAUTHORIZED; } + @Override public Map getChallenges( final HttpResponse response, final HttpContext context) throws MalformedChallengeException { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java index 52d8875395..5a1827af1b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java @@ -156,6 +156,7 @@ protected final void assertValid( } } + @Override public boolean isOpen() { final OperatedClientConnection conn = getWrappedConnection(); if (conn == null) { @@ -165,6 +166,7 @@ public boolean isOpen() { return conn.isOpen(); } + @Override public boolean isStale() { if (isReleased()) { return true; @@ -177,36 +179,42 @@ public boolean isStale() { return conn.isStale(); } + @Override public void setSocketTimeout(final int timeout) { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); conn.setSocketTimeout(timeout); } + @Override public int getSocketTimeout() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.getSocketTimeout(); } + @Override public HttpConnectionMetrics getMetrics() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.getMetrics(); } + @Override public void flush() throws IOException { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); conn.flush(); } + @Override public boolean isResponseAvailable(final int timeout) throws IOException { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.isResponseAvailable(timeout); } + @Override public void receiveResponseEntity(final HttpResponse response) throws HttpException, IOException { final OperatedClientConnection conn = getWrappedConnection(); @@ -215,6 +223,7 @@ public void receiveResponseEntity(final HttpResponse response) conn.receiveResponseEntity(response); } + @Override public HttpResponse receiveResponseHeader() throws HttpException, IOException { final OperatedClientConnection conn = getWrappedConnection(); @@ -223,6 +232,7 @@ public HttpResponse receiveResponseHeader() return conn.receiveResponseHeader(); } + @Override public void sendRequestEntity(final HttpEntityEnclosingRequest request) throws HttpException, IOException { final OperatedClientConnection conn = getWrappedConnection(); @@ -231,6 +241,7 @@ public void sendRequestEntity(final HttpEntityEnclosingRequest request) conn.sendRequestEntity(request); } + @Override public void sendRequestHeader(final HttpRequest request) throws HttpException, IOException { final OperatedClientConnection conn = getWrappedConnection(); @@ -239,40 +250,47 @@ public void sendRequestHeader(final HttpRequest request) conn.sendRequestHeader(request); } + @Override public InetAddress getLocalAddress() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.getLocalAddress(); } + @Override public int getLocalPort() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.getLocalPort(); } + @Override public InetAddress getRemoteAddress() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.getRemoteAddress(); } + @Override public int getRemotePort() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.getRemotePort(); } + @Override public boolean isSecure() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); return conn.isSecure(); } + @Override public void bind(final Socket socket) throws IOException { throw new UnsupportedOperationException(); } + @Override public Socket getSocket() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); @@ -282,6 +300,7 @@ public Socket getSocket() { return conn.getSocket(); } + @Override public SSLSession getSSLSession() { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); @@ -297,18 +316,22 @@ public SSLSession getSSLSession() { return result; } + @Override public void markReusable() { markedReusable = true; } + @Override public void unmarkReusable() { markedReusable = false; } + @Override public boolean isMarkedReusable() { return markedReusable; } + @Override public void setIdleDuration(final long duration, final TimeUnit unit) { if(duration > 0) { this.duration = unit.toMillis(duration); @@ -317,6 +340,7 @@ public void setIdleDuration(final long duration, final TimeUnit unit) { } } + @Override public synchronized void releaseConnection() { if (released) { return; @@ -325,6 +349,7 @@ public synchronized void releaseConnection() { connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS); } + @Override public synchronized void abortConnection() { if (released) { return; @@ -338,6 +363,7 @@ public synchronized void abortConnection() { connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS); } + @Override public Object getAttribute(final String id) { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); @@ -348,6 +374,7 @@ public Object getAttribute(final String id) { } } + @Override public Object removeAttribute(final String id) { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); @@ -358,6 +385,7 @@ public Object removeAttribute(final String id) { } } + @Override public void setAttribute(final String id, final Object obj) { final OperatedClientConnection conn = getWrappedConnection(); assertValid(conn); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractPooledConnAdapter.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractPooledConnAdapter.java index 79bc61931e..85860bb440 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractPooledConnAdapter.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractPooledConnAdapter.java @@ -67,6 +67,7 @@ protected AbstractPooledConnAdapter(final ClientConnectionManager manager, this.poolEntry = entry; } + @Override public String getId() { return null; } @@ -117,12 +118,14 @@ protected synchronized void detach() { super.detach(); } + @Override public HttpRoute getRoute() { final AbstractPoolEntry entry = getPoolEntry(); assertValid(entry); return (entry.tracker == null) ? null : entry.tracker.toRoute(); } + @Override public void open(final HttpRoute route, final HttpContext context, final HttpParams params) throws IOException { @@ -131,6 +134,7 @@ public void open(final HttpRoute route, entry.open(route, context, params); } + @Override public void tunnelTarget(final boolean secure, final HttpParams params) throws IOException { final AbstractPoolEntry entry = getPoolEntry(); @@ -138,6 +142,7 @@ public void tunnelTarget(final boolean secure, final HttpParams params) entry.tunnelTarget(secure, params); } + @Override public void tunnelProxy(final HttpHost next, final boolean secure, final HttpParams params) throws IOException { final AbstractPoolEntry entry = getPoolEntry(); @@ -145,6 +150,7 @@ public void tunnelProxy(final HttpHost next, final boolean secure, final HttpPar entry.tunnelProxy(next, secure, params); } + @Override public void layerProtocol(final HttpContext context, final HttpParams params) throws IOException { final AbstractPoolEntry entry = getPoolEntry(); @@ -152,6 +158,7 @@ public void layerProtocol(final HttpContext context, final HttpParams params) entry.layerProtocol(context, params); } + @Override public void close() throws IOException { final AbstractPoolEntry entry = getPoolEntry(); if (entry != null) { @@ -164,6 +171,7 @@ public void close() throws IOException { } } + @Override public void shutdown() throws IOException { final AbstractPoolEntry entry = getPoolEntry(); if (entry != null) { @@ -176,12 +184,14 @@ public void shutdown() throws IOException { } } + @Override public Object getState() { final AbstractPoolEntry entry = getPoolEntry(); assertValid(entry); return entry.getState(); } + @Override public void setState(final Object state) { final AbstractPoolEntry entry = getPoolEntry(); assertValid(entry); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java index 7a2baed3f4..9e424a48c9 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java @@ -121,6 +121,7 @@ protected void finalize() throws Throwable { } } + @Override public SchemeRegistry getSchemeRegistry() { return this.schemeRegistry; } @@ -129,16 +130,19 @@ protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry return new DefaultClientConnectionOperator(schreg); } + @Override public final ClientConnectionRequest requestConnection( final HttpRoute route, final Object state) { return new ClientConnectionRequest() { + @Override public void abortRequest() { // Nothing to abort, since requests are immediate. } + @Override public ManagedClientConnection getConnection( final long timeout, final TimeUnit tunit) { return BasicClientConnectionManager.this.getConnection( @@ -189,6 +193,7 @@ private void shutdownConnection(final HttpClientConnection conn) { } } + @Override public void releaseConnection(final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) { Args.check(conn instanceof ManagedClientConnectionImpl, "Connection class mismatch, " + "connection not obtained from this manager"); @@ -234,6 +239,7 @@ public void releaseConnection(final ManagedClientConnection conn, final long kee } } + @Override public void closeExpiredConnections() { synchronized (this) { assertNotShutdown(); @@ -245,6 +251,7 @@ public void closeExpiredConnections() { } } + @Override public void closeIdleConnections(final long idletime, final TimeUnit tunit) { Args.notNull(tunit, "Time unit"); synchronized (this) { @@ -261,6 +268,7 @@ public void closeIdleConnections(final long idletime, final TimeUnit tunit) { } } + @Override public void shutdown() { synchronized (this) { this.shutdown = true; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java index ab83d08b7f..5a29784c4f 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java @@ -93,14 +93,17 @@ public DefaultClientConnection() { this.attributes = new HashMap(); } + @Override public String getId() { return null; } + @Override public final HttpHost getTargetHost() { return this.targetHost; } + @Override public final boolean isSecure() { return this.connSecure; } @@ -110,6 +113,7 @@ public final Socket getSocket() { return this.socket; } + @Override public SSLSession getSSLSession() { if (this.socket instanceof SSLSocket) { return ((SSLSocket) this.socket).getSession(); @@ -118,6 +122,7 @@ public SSLSession getSSLSession() { } } + @Override public void opening(final Socket sock, final HttpHost target) throws IOException { assertNotOpen(); this.socket = sock; @@ -131,6 +136,7 @@ public void opening(final Socket sock, final HttpHost target) throws IOException } } + @Override public void openCompleted(final boolean secure, final HttpParams params) throws IOException { Args.notNull(params, "Parameters"); assertNotOpen(); @@ -226,10 +232,12 @@ protected HttpMessageParser createResponseParser( (buffer, null, responseFactory, params); } + @Override public void bind(final Socket socket) throws IOException { bind(socket, new BasicHttpParams()); } + @Override public void update(final Socket sock, final HttpHost target, final boolean secure, final HttpParams params) throws IOException { @@ -277,14 +285,17 @@ public void sendRequestHeader(final HttpRequest request) throws HttpException, I } } + @Override public Object getAttribute(final String id) { return this.attributes.get(id); } + @Override public Object removeAttribute(final String id) { return this.attributes.remove(id); } + @Override public void setAttribute(final String id, final Object obj) { this.attributes.put(id, obj); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java index fb1a719a83..ee14079f11 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java @@ -128,6 +128,7 @@ public DefaultClientConnectionOperator(final SchemeRegistry schemes,final DnsRes this.dnsResolver = dnsResolver; } + @Override public OperatedClientConnection createConnection() { return new DefaultClientConnection(); } @@ -141,6 +142,7 @@ private SchemeRegistry getSchemeRegistry(final HttpContext context) { return reg; } + @Override public void openConnection( final OperatedClientConnection conn, final HttpHost target, @@ -198,6 +200,7 @@ public void openConnection( } } + @Override public void updateSecureConnection( final OperatedClientConnection conn, final HttpHost target, diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java index e624c94c55..650c202494 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java @@ -78,6 +78,7 @@ public DefaultHttpRoutePlanner(final SchemeRegistry schreg) { schemeRegistry = schreg; } + @Override public HttpRoute determineRoute(final HttpHost target, final HttpRequest request, final HttpContext context) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java index 75e4eac272..c89dbe402c 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java @@ -75,6 +75,7 @@ static class InternalConnFactory implements ConnFactory 0) { @@ -87,6 +89,7 @@ public int read(final byte[] b, final int off, final int len) throws IOException return l; } + @Override public int read() throws IOException { final int l = this.in.read(); if (this.wire.enabled() && l != -1) { @@ -95,6 +98,7 @@ public int read() throws IOException { return l; } + @Override public int read(final byte[] b) throws IOException { final int l = this.in.read(b); if (this.wire.enabled() && l > 0) { @@ -103,6 +107,7 @@ public int read(final byte[] b) throws IOException { return l; } + @Override public String readLine() throws IOException { final String s = this.in.readLine(); if (this.wire.enabled() && s != null) { @@ -112,6 +117,7 @@ public String readLine() throws IOException { return s; } + @Override public int readLine(final CharArrayBuffer buffer) throws IOException { final int l = this.in.readLine(buffer); if (this.wire.enabled() && l >= 0) { @@ -123,10 +129,12 @@ public int readLine(final CharArrayBuffer buffer) throws IOException { return l; } + @Override public HttpTransportMetrics getMetrics() { return this.in.getMetrics(); } + @Override public boolean isEof() { if (this.eofSensor != null) { return this.eofSensor.isEof(); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java index 8d8fc8a9d8..a4e9912710 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java @@ -69,6 +69,7 @@ public LoggingSessionOutputBuffer(final SessionOutputBuffer out, final Wire wire this(out, wire, null); } + @Override public void write(final byte[] b, final int off, final int len) throws IOException { this.out.write(b, off, len); if (this.wire.enabled()) { @@ -76,6 +77,7 @@ public void write(final byte[] b, final int off, final int len) throws IOExcepti } } + @Override public void write(final int b) throws IOException { this.out.write(b); if (this.wire.enabled()) { @@ -83,6 +85,7 @@ public void write(final int b) throws IOException { } } + @Override public void write(final byte[] b) throws IOException { this.out.write(b); if (this.wire.enabled()) { @@ -90,10 +93,12 @@ public void write(final byte[] b) throws IOException { } } + @Override public void flush() throws IOException { this.out.flush(); } + @Override public void writeLine(final CharArrayBuffer buffer) throws IOException { this.out.writeLine(buffer); if (this.wire.enabled()) { @@ -103,6 +108,7 @@ public void writeLine(final CharArrayBuffer buffer) throws IOException { } } + @Override public void writeLine(final String s) throws IOException { this.out.writeLine(s); if (this.wire.enabled()) { @@ -111,6 +117,7 @@ public void writeLine(final String s) throws IOException { } } + @Override public HttpTransportMetrics getMetrics() { return this.out.getMetrics(); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java index 29a4430715..7b5b70f92a 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java @@ -83,6 +83,7 @@ class ManagedClientConnectionImpl implements ManagedClientConnection { this.duration = Long.MAX_VALUE; } + @Override public String getId() { return null; } @@ -125,6 +126,7 @@ private HttpPoolEntry ensurePoolEntry() { return local; } + @Override public void close() throws IOException { final HttpPoolEntry local = this.poolEntry; if (local != null) { @@ -134,6 +136,7 @@ public void close() throws IOException { } } + @Override public void shutdown() throws IOException { final HttpPoolEntry local = this.poolEntry; if (local != null) { @@ -143,6 +146,7 @@ public void shutdown() throws IOException { } } + @Override public boolean isOpen() { final OperatedClientConnection conn = getConnection(); if (conn != null) { @@ -152,6 +156,7 @@ public boolean isOpen() { } } + @Override public boolean isStale() { final OperatedClientConnection conn = getConnection(); if (conn != null) { @@ -161,88 +166,105 @@ public boolean isStale() { } } + @Override public void setSocketTimeout(final int timeout) { final OperatedClientConnection conn = ensureConnection(); conn.setSocketTimeout(timeout); } + @Override public int getSocketTimeout() { final OperatedClientConnection conn = ensureConnection(); return conn.getSocketTimeout(); } + @Override public HttpConnectionMetrics getMetrics() { final OperatedClientConnection conn = ensureConnection(); return conn.getMetrics(); } + @Override public void flush() throws IOException { final OperatedClientConnection conn = ensureConnection(); conn.flush(); } + @Override public boolean isResponseAvailable(final int timeout) throws IOException { final OperatedClientConnection conn = ensureConnection(); return conn.isResponseAvailable(timeout); } + @Override public void receiveResponseEntity( final HttpResponse response) throws HttpException, IOException { final OperatedClientConnection conn = ensureConnection(); conn.receiveResponseEntity(response); } + @Override public HttpResponse receiveResponseHeader() throws HttpException, IOException { final OperatedClientConnection conn = ensureConnection(); return conn.receiveResponseHeader(); } + @Override public void sendRequestEntity( final HttpEntityEnclosingRequest request) throws HttpException, IOException { final OperatedClientConnection conn = ensureConnection(); conn.sendRequestEntity(request); } + @Override public void sendRequestHeader( final HttpRequest request) throws HttpException, IOException { final OperatedClientConnection conn = ensureConnection(); conn.sendRequestHeader(request); } + @Override public InetAddress getLocalAddress() { final OperatedClientConnection conn = ensureConnection(); return conn.getLocalAddress(); } + @Override public int getLocalPort() { final OperatedClientConnection conn = ensureConnection(); return conn.getLocalPort(); } + @Override public InetAddress getRemoteAddress() { final OperatedClientConnection conn = ensureConnection(); return conn.getRemoteAddress(); } + @Override public int getRemotePort() { final OperatedClientConnection conn = ensureConnection(); return conn.getRemotePort(); } + @Override public boolean isSecure() { final OperatedClientConnection conn = ensureConnection(); return conn.isSecure(); } + @Override public void bind(final Socket socket) throws IOException { throw new UnsupportedOperationException(); } + @Override public Socket getSocket() { final OperatedClientConnection conn = ensureConnection(); return conn.getSocket(); } + @Override public SSLSession getSSLSession() { final OperatedClientConnection conn = ensureConnection(); SSLSession result = null; @@ -278,11 +300,13 @@ public void setAttribute(final String id, final Object obj) { } } + @Override public HttpRoute getRoute() { final HttpPoolEntry local = ensurePoolEntry(); return local.getEffectiveRoute(); } + @Override public void open( final HttpRoute route, final HttpContext context, @@ -320,6 +344,7 @@ public void open( } } + @Override public void tunnelTarget( final boolean secure, final HttpParams params) throws IOException { Args.notNull(params, "HTTP parameters"); @@ -348,6 +373,7 @@ public void tunnelTarget( } } + @Override public void tunnelProxy( final HttpHost next, final boolean secure, final HttpParams params) throws IOException { Args.notNull(next, "Next proxy"); @@ -374,6 +400,7 @@ public void tunnelProxy( } } + @Override public void layerProtocol( final HttpContext context, final HttpParams params) throws IOException { Args.notNull(params, "HTTP parameters"); @@ -402,28 +429,34 @@ public void layerProtocol( } } + @Override public Object getState() { final HttpPoolEntry local = ensurePoolEntry(); return local.getState(); } + @Override public void setState(final Object state) { final HttpPoolEntry local = ensurePoolEntry(); local.setState(state); } + @Override public void markReusable() { this.reusable = true; } + @Override public void unmarkReusable() { this.reusable = false; } + @Override public boolean isMarkedReusable() { return this.reusable; } + @Override public void setIdleDuration(final long duration, final TimeUnit unit) { if(duration > 0) { this.duration = unit.toMillis(duration); @@ -432,6 +465,7 @@ public void setIdleDuration(final long duration, final TimeUnit unit) { } } + @Override public void releaseConnection() { synchronized (this) { if (this.poolEntry == null) { @@ -442,6 +476,7 @@ public void releaseConnection() { } } + @Override public void abortConnection() { synchronized (this) { if (this.poolEntry == null) { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java index 077fa7dedf..a4e5f286a1 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java @@ -138,6 +138,7 @@ protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry return new DefaultClientConnectionOperator(schreg, this.dnsResolver); } + @Override public SchemeRegistry getSchemeRegistry() { return this.schemeRegistry; } @@ -174,6 +175,7 @@ private String format(final HttpPoolEntry entry) { return buf.toString(); } + @Override public ClientConnectionRequest requestConnection( final HttpRoute route, final Object state) { @@ -185,10 +187,12 @@ public ClientConnectionRequest requestConnection( return new ClientConnectionRequest() { + @Override public void abortRequest() { future.cancel(true); } + @Override public ManagedClientConnection getConnection( final long timeout, final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException { @@ -227,6 +231,7 @@ ManagedClientConnection leaseConnection( } } + @Override public void releaseConnection( final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) { @@ -271,6 +276,7 @@ public void releaseConnection( } } + @Override public void shutdown() { this.log.debug("Connection manager is shutting down"); try { @@ -281,6 +287,7 @@ public void shutdown() { this.log.debug("Connection manager shut down"); } + @Override public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { if (this.log.isDebugEnabled()) { this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); @@ -288,39 +295,48 @@ public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { this.pool.closeIdle(idleTimeout, tunit); } + @Override public void closeExpiredConnections() { this.log.debug("Closing expired connections"); this.pool.closeExpired(); } + @Override public int getMaxTotal() { return this.pool.getMaxTotal(); } + @Override public void setMaxTotal(final int max) { this.pool.setMaxTotal(max); } + @Override public int getDefaultMaxPerRoute() { return this.pool.getDefaultMaxPerRoute(); } + @Override public void setDefaultMaxPerRoute(final int max) { this.pool.setDefaultMaxPerRoute(max); } + @Override public int getMaxPerRoute(final HttpRoute route) { return this.pool.getMaxPerRoute(route); } + @Override public void setMaxPerRoute(final HttpRoute route, final int max) { this.pool.setMaxPerRoute(route, max); } + @Override public PoolStats getTotalStats() { return this.pool.getTotalStats(); } + @Override public PoolStats getStats(final HttpRoute route) { return this.pool.getStats(route); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java index 69d714b129..2fe96d1ff4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java @@ -114,6 +114,7 @@ public void setProxySelector(final ProxySelector prosel) { this.proxySelector = prosel; } + @Override public HttpRoute determineRoute(final HttpHost target, final HttpRequest request, final HttpContext context) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java index d3bfc9b668..774cf4a370 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java @@ -145,6 +145,7 @@ protected void finalize() throws Throwable { } } + @Override public SchemeRegistry getSchemeRegistry() { return this.schemeRegistry; } @@ -175,16 +176,19 @@ protected final void assertStillUp() throws IllegalStateException { Asserts.check(!this.isShutDown, "Manager is shut down"); } + @Override public final ClientConnectionRequest requestConnection( final HttpRoute route, final Object state) { return new ClientConnectionRequest() { + @Override public void abortRequest() { // Nothing to abort, since requests are immediate. } + @Override public ManagedClientConnection getConnection( final long timeout, final TimeUnit tunit) { return SingleClientConnManager.this.getConnection( @@ -253,6 +257,7 @@ public ManagedClientConnection getConnection(final HttpRoute route, final Object } } + @Override public void releaseConnection( final ManagedClientConnection conn, final long validDuration, final TimeUnit timeUnit) { @@ -307,6 +312,7 @@ public void releaseConnection( } } + @Override public void closeExpiredConnections() { final long time = connectionExpiresTime; if (System.currentTimeMillis() >= time) { @@ -314,6 +320,7 @@ public void closeExpiredConnections() { } } + @Override public void closeIdleConnections(final long idletime, final TimeUnit tunit) { assertStillUp(); @@ -336,6 +343,7 @@ public void closeIdleConnections(final long idletime, final TimeUnit tunit) { } } + @Override public void shutdown() { this.isShutDown = true; synchronized (this) { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java index 7c1bace0c1..31914c47f5 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java @@ -282,6 +282,7 @@ public PoolEntryRequest requestPoolEntry( return new PoolEntryRequest() { + @Override public void abortRequest() { poolLock.lock(); try { @@ -291,6 +292,7 @@ public void abortRequest() { } } + @Override public BasicPoolEntry getPoolEntry( final long timeout, final TimeUnit tunit) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/RouteSpecificPool.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/RouteSpecificPool.java index 875802f707..9e463430c3 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/RouteSpecificPool.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/RouteSpecificPool.java @@ -84,6 +84,7 @@ public RouteSpecificPool(final HttpRoute route, final int maxEntries) { this.route = route; this.maxEntries = maxEntries; this.connPerRoute = new ConnPerRoute() { + @Override public int getMaxForRoute(final HttpRoute unused) { return RouteSpecificPool.this.maxEntries; } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java index 2a3538e48e..5bda67c36f 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java @@ -209,10 +209,12 @@ protected ConnPoolByRoute createConnectionPool(final long connTTL, final TimeUni return new DefaultClientConnectionOperator(schreg);// @ThreadSafe } + @Override public SchemeRegistry getSchemeRegistry() { return this.schemeRegistry; } + @Override public ClientConnectionRequest requestConnection( final HttpRoute route, final Object state) { @@ -222,10 +224,12 @@ public ClientConnectionRequest requestConnection( return new ClientConnectionRequest() { + @Override public void abortRequest() { poolRequest.abortRequest(); } + @Override public ManagedClientConnection getConnection( final long timeout, final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException { @@ -243,6 +247,7 @@ public ManagedClientConnection getConnection( } + @Override public void releaseConnection(final ManagedClientConnection conn, final long validDuration, final TimeUnit timeUnit) { Args.check(conn instanceof BasicPooledConnAdapter, "Connection class mismatch, " + "connection not obtained from this manager"); @@ -288,6 +293,7 @@ public void releaseConnection(final ManagedClientConnection conn, final long val } } + @Override public void shutdown() { log.debug("Shutting down"); pool.shutdown(); @@ -319,6 +325,7 @@ public int getConnectionsInPool() { return pool.getConnectionsInPool(); } + @Override public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { if (log.isDebugEnabled()) { log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); @@ -326,6 +333,7 @@ public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { pool.closeIdleConnections(idleTimeout, tunit); } + @Override public void closeExpiredConnections() { log.debug("Closing expired connections"); pool.closeExpiredConnections(); diff --git a/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java b/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java index 05cb43357f..16d0c5bf05 100644 --- a/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java @@ -58,10 +58,12 @@ public GSSCredential getGSSCredential() { return gssCredential; } + @Override public Principal getUserPrincipal() { return null; } + @Override public String getPassword() { return null; } diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java index 81d4d7ee72..e9e9e57994 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -129,6 +129,7 @@ public final boolean verify(final String host, final SSLSession session) { } } + @Override public final void verify( final String host, final X509Certificate cert) throws SSLException { final boolean ipv4 = InetAddressUtils.isIPv4Address(host); diff --git a/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java b/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java index 07c43b6f28..071aa87376 100644 --- a/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java +++ b/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java @@ -130,30 +130,37 @@ public void addPart(final String name, final ContentBody contentBody) { addPart(new FormBodyPart(name, contentBody)); } + @Override public boolean isRepeatable() { return getEntity().isRepeatable(); } + @Override public boolean isChunked() { return getEntity().isChunked(); } + @Override public boolean isStreaming() { return getEntity().isStreaming(); } + @Override public long getContentLength() { return getEntity().getContentLength(); } + @Override public Header getContentType() { return getEntity().getContentType(); } + @Override public Header getContentEncoding() { return getEntity().getContentEncoding(); } + @Override public void consumeContent() throws IOException, UnsupportedOperationException{ if (isStreaming()) { @@ -162,11 +169,13 @@ public void consumeContent() } } + @Override public InputStream getContent() throws IOException, UnsupportedOperationException { throw new UnsupportedOperationException( "Multipart form entity does not implement #getContent()"); } + @Override public void writeTo(final OutputStream outstream) throws IOException { getEntity().writeTo(outstream); } From 9d5dde271f2714bc97bf39c7d66b26e3540b18ed Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 27 Jan 2016 09:00:25 +0000 Subject: [PATCH 051/204] Add final modifier to private fields. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1726967 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/impl/client/cache/CacheConfig.java | 4 ++-- .../apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java | 2 +- .../http/impl/auth/win/WindowsNegotiateSchemeFactory.java | 2 +- .../org/apache/http/conn/ssl/SSLContextBuilder.java | 4 ++-- .../org/apache/http/client/entity/DeflateInputStream.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java index 3c4a55e7a1..89fda7f156 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java @@ -164,8 +164,8 @@ public class CacheConfig implements Cloneable { private long maxObjectSize; private int maxCacheEntries; private int maxUpdateRetries; - private boolean allow303Caching; - private boolean weakETagOnPutDeleteAllowed; + private final boolean allow303Caching; + private final boolean weakETagOnPutDeleteAllowed; private boolean heuristicCachingEnabled; private float heuristicCoefficient; private long heuristicDefaultLifetime; diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java index 94f715a505..21bed6409e 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java @@ -45,7 +45,7 @@ @Immutable public class WindowsNTLMSchemeFactory implements AuthSchemeProvider { - private String servicePrincipalName; + private final String servicePrincipalName; public WindowsNTLMSchemeFactory(final String servicePrincipalName) { super(); diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java index b1e3e57434..29e5ffdb58 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java @@ -45,7 +45,7 @@ @Immutable public class WindowsNegotiateSchemeFactory implements AuthSchemeProvider { - private String servicePrincipalName; + private final String servicePrincipalName; public WindowsNegotiateSchemeFactory(final String servicePrincipalName) { super(); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java index 44aa39799f..c54db0c52a 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java @@ -68,8 +68,8 @@ public class SSLContextBuilder { static final String SSL = "SSL"; private String protocol; - private Set keymanagers; - private Set trustmanagers; + private final Set keymanagers; + private final Set trustmanagers; private SecureRandom secureRandom; public SSLContextBuilder() { diff --git a/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java index 24f7d048b3..75d5a6ac79 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStream.java @@ -39,7 +39,7 @@ */ public class DeflateInputStream extends InputStream { - private InputStream sourceStream; + private final InputStream sourceStream; public DeflateInputStream(final InputStream wrapped) throws IOException { From ac5e71b6aae096607c5a6357a8f70fde3b4107d8 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 27 Jan 2016 09:04:42 +0000 Subject: [PATCH 052/204] Add final modifier to local variables. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1726971 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/auth/win/WindowsNegotiateScheme.java | 4 ++-- .../org/apache/http/impl/client/WinHttpClients.java | 2 +- .../http/impl/client/CloseableHttpResponseProxy.java | 8 ++++---- .../apache/http/client/methods/RequestBuilder.java | 2 +- .../java/org/apache/http/client/utils/URIUtils.java | 4 ++-- .../apache/http/client/utils/URLEncodedUtils.java | 2 +- .../org/apache/http/conn/ssl/AbstractVerifier.java | 4 ++-- .../http/conn/ssl/DefaultHostnameVerifier.java | 6 +++--- .../http/conn/ssl/SSLConnectionSocketFactory.java | 4 ++-- .../apache/http/conn/util/PublicSuffixMatcher.java | 10 +++++----- .../http/conn/util/PublicSuffixMatcherLoader.java | 2 +- .../org/apache/http/impl/auth/GGSSchemeBase.java | 2 +- .../org/apache/http/impl/client/BasicAuthCache.java | 6 +++--- .../apache/http/impl/client/HttpClientBuilder.java | 2 +- .../http/impl/client/IdleConnectionEvictor.java | 2 +- .../apache/http/impl/conn/LoggingInputStream.java | 12 ++++++------ .../apache/http/impl/conn/LoggingOutputStream.java | 10 +++++----- .../apache/http/impl/cookie/AbstractCookieSpec.java | 2 +- .../apache/http/impl/cookie/LaxExpiresHandler.java | 2 +- .../apache/http/impl/cookie/RFC6265CookieSpec.java | 4 ++-- .../http/impl/execchain/ResponseEntityProxy.java | 12 ++++++------ .../java/org/apache/http/client/entity/TestGZip.java | 2 +- .../http/conn/ssl/TestDefaultHostnameVerifier.java | 8 ++++---- .../apache/http/entity/mime/FormBodyPartBuilder.java | 2 +- 24 files changed, 57 insertions(+), 57 deletions(-) diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java index 29a6b42caf..3b0223f223 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java @@ -188,7 +188,7 @@ public Header authenticate( final String targetName = getServicePrincipalName(context); response = getToken(null, null, targetName); - } catch (RuntimeException ex) { + } catch (final RuntimeException ex) { failAuthCleanup(); if (ex instanceof Win32Exception) { throw new AuthenticationException("Authentication Failed", ex); @@ -206,7 +206,7 @@ public Header authenticate( Sspi.SECBUFFER_TOKEN, continueTokenBytes); final String targetName = getServicePrincipalName(context); response = getToken(this.sspiContext, continueTokenBuffer, targetName); - } catch (RuntimeException ex) { + } catch (final RuntimeException ex) { failAuthCleanup(); if (ex instanceof Win32Exception) { throw new AuthenticationException("Authentication Failed", ex); diff --git a/httpclient-win/src/main/java/org/apache/http/impl/client/WinHttpClients.java b/httpclient-win/src/main/java/org/apache/http/impl/client/WinHttpClients.java index 8b81fc5128..396f20afbf 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/client/WinHttpClients.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/client/WinHttpClients.java @@ -59,7 +59,7 @@ public static boolean isWinAuthAvailable() { if (os != null && os.contains("windows")) { try { return Sspi.MAX_TOKEN_SIZE > 0; - } catch (Exception ignore) { // Likely ClassNotFound + } catch (final Exception ignore) { // Likely ClassNotFound return false; } } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java index bd41fc62fc..aa3fcec7a4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java @@ -53,7 +53,7 @@ class CloseableHttpResponseProxy implements InvocationHandler { try { CONSTRUCTOR = Proxy.getProxyClass(CloseableHttpResponseProxy.class.getClassLoader(), new Class[] { CloseableHttpResponse.class }).getConstructor(new Class[] { InvocationHandler.class }); - } catch (NoSuchMethodException ex) { + } catch (final NoSuchMethodException ex) { throw new IllegalStateException(ex); } } @@ -94,11 +94,11 @@ public Object invoke( public static CloseableHttpResponse newProxy(final HttpResponse original) { try { return (CloseableHttpResponse) CONSTRUCTOR.newInstance(new CloseableHttpResponseProxy(original)); - } catch (InstantiationException ex) { + } catch (final InstantiationException ex) { throw new IllegalStateException(ex); - } catch (InvocationTargetException ex) { + } catch (final InvocationTargetException ex) { throw new IllegalStateException(ex); - } catch (IllegalAccessException ex) { + } catch (final IllegalAccessException ex) { throw new IllegalStateException(ex); } } diff --git a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java index 9c00b5da6d..f6cd6816bc 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java @@ -284,7 +284,7 @@ private RequestBuilder doCopy(final HttpRequest request) { if (!formParams.isEmpty()) { parameters = formParams; } - } catch (IOException ignore) { + } catch (final IOException ignore) { } } else { entity = originalEntity; diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java index aecee1ada2..72c299ef94 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java @@ -270,7 +270,7 @@ public static URI resolve(final URI baseURI, final URI reference){ } try { return normalizeSyntax(resolved); - } catch (URISyntaxException ex) { + } catch (final URISyntaxException ex) { throw new IllegalArgumentException(ex); } } @@ -381,7 +381,7 @@ public static HttpHost extractHost(final URI uri) { if (!TextUtils.isBlank(host)) { try { target = new HttpHost(host, port, scheme); - } catch (IllegalArgumentException ignore) { + } catch (final IllegalArgumentException ignore) { } } } diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index 958a98a768..de18e6d58e 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -279,7 +279,7 @@ public static List parse( Args.notNull(buf, "Char array buffer"); final TokenParser tokenParser = TokenParser.INSTANCE; final BitSet delimSet = new BitSet(); - for (char separator: separators) { + for (final char separator: separators) { delimSet.set(separator); } final ParserCursor cursor = new ParserCursor(0, buf.length()); diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java index e9e9e57994..5950dff018 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -155,7 +155,7 @@ public final void verify(final String host, final String[] cns, DefaultHostnameVerifier.normaliseAddress(host.toLowerCase(Locale.ROOT)) : host; if (subjectAltList != null) { - for (String subjectAlt: subjectAltList) { + for (final String subjectAlt: subjectAltList) { final String normalizedAltSubject = InetAddressUtils.isIPv6Address(subjectAlt) ? DefaultHostnameVerifier.normaliseAddress(subjectAlt) : subjectAlt; if (matchIdentity(normalizedHost, normalizedAltSubject, strictWithSubDomains)) { @@ -223,7 +223,7 @@ public static String[] getCNs(final X509Certificate cert) { try { final String cn = DefaultHostnameVerifier.extractCN(subjectPrincipal); return cn != null ? new String[] { cn } : null; - } catch (SSLException ex) { + } catch (final SSLException ex) { return null; } } diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 8b9d52659c..8539791992 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -262,13 +262,13 @@ static String extractCN(final String subjectPrincipal) throws SSLException { if (value != null) { return value.toString(); } - } catch (NoSuchElementException ignore) { - } catch (NamingException ignore) { + } catch (final NoSuchElementException ignore) { + } catch (final NamingException ignore) { } } } return null; - } catch (InvalidNameException e) { + } catch (final InvalidNameException e) { throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name"); } } diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java index 15923e7ab3..df8689b420 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java @@ -371,7 +371,7 @@ public Socket createLayeredSocket( // If supported protocols are not explicitly set, remove all SSL protocol versions final String[] allProtocols = sslsock.getEnabledProtocols(); final List enabledProtocols = new ArrayList(allProtocols.length); - for (String protocol: allProtocols) { + for (final String protocol: allProtocols) { if (!protocol.startsWith("SSL")) { enabledProtocols.add(protocol); } @@ -454,7 +454,7 @@ private void verifyHostname(final SSLSocket sslsock, final String hostname) thro } this.log.debug(" issuer alternative names: " + altNames); } - } catch (Exception ignore) { + } catch (final Exception ignore) { } } diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java index 30c666fbb1..2ec340f613 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java @@ -64,12 +64,12 @@ public PublicSuffixMatcher( Args.notNull(domainType, "Domain type"); Args.notNull(rules, "Domain suffix rules"); this.rules = new ConcurrentHashMap(rules.size()); - for (String rule: rules) { + for (final String rule: rules) { this.rules.put(rule, domainType); } this.exceptions = new ConcurrentHashMap(); if (exceptions != null) { - for (String exception: exceptions) { + for (final String exception: exceptions) { this.exceptions.put(exception, domainType); } } @@ -82,15 +82,15 @@ public PublicSuffixMatcher(final Collection lists) { Args.notNull(lists, "Domain suffix lists"); this.rules = new ConcurrentHashMap(); this.exceptions = new ConcurrentHashMap(); - for (PublicSuffixList list: lists) { + for (final PublicSuffixList list: lists) { final DomainType domainType = list.getType(); final List rules = list.getRules(); - for (String rule: rules) { + for (final String rule: rules) { this.rules.put(rule, domainType); } final List exceptions = list.getExceptions(); if (exceptions != null) { - for (String exception: exceptions) { + for (final String exception: exceptions) { this.exceptions.put(exception, domainType); } } diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java index 3c75f9d3cd..5a25b4610c 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java @@ -86,7 +86,7 @@ public static PublicSuffixMatcher getDefault() { if (url != null) { try { DEFAULT_INSTANCE = load(url); - } catch (IOException ex) { + } catch (final IOException ex) { // Should never happen final Log log = LogFactory.getLog(PublicSuffixMatcherLoader.class); if (log.isWarnEnabled()) { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java index 502be3cb0b..ffb22b023e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java @@ -205,7 +205,7 @@ public Header authenticate( //final DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE; //hostname = dnsResolver.resolveCanonicalHostname(host.getHostName()); hostname = resolveCanonicalHostname(hostname); - } catch (UnknownHostException ignore){ + } catch (final UnknownHostException ignore){ } } if (this.stripPort) { // || host.getPort()==80 || host.getPort()==443) { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java index bd4898c5e7..97dabb3d73 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java @@ -107,7 +107,7 @@ public void put(final HttpHost host, final AuthScheme authScheme) { out.writeObject(authScheme); out.close(); this.map.put(getKey(host), buf.toByteArray()); - } catch (IOException ex) { + } catch (final IOException ex) { if (log.isWarnEnabled()) { log.warn("Unexpected I/O error while serializing auth scheme", ex); } @@ -130,12 +130,12 @@ public AuthScheme get(final HttpHost host) { final AuthScheme authScheme = (AuthScheme) in.readObject(); in.close(); return authScheme; - } catch (IOException ex) { + } catch (final IOException ex) { if (log.isWarnEnabled()) { log.warn("Unexpected I/O error while de-serializing auth scheme", ex); } return null; - } catch (ClassNotFoundException ex) { + } catch (final ClassNotFoundException ex) { if (log.isWarnEnabled()) { log.warn("Unexpected error while de-serializing auth scheme", ex); } diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 943848cb6e..5dd61624e4 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -1102,7 +1102,7 @@ public CloseableHttpClient build() { if (!contentCompressionDisabled) { if (contentDecoderMap != null) { final RegistryBuilder b2 = RegistryBuilder.create(); - for (Map.Entry entry: contentDecoderMap.entrySet()) { + for (final Map.Entry entry: contentDecoderMap.entrySet()) { b2.register(entry.getKey(), entry.getValue()); } b.add(new ResponseContentEncoding(b2.build())); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java b/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java index 6bd8c8084b..b95b5083b9 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java @@ -69,7 +69,7 @@ public void run() { connectionManager.closeIdleConnections(maxIdleTimeMs, TimeUnit.MILLISECONDS); } } - } catch (Exception ex) { + } catch (final Exception ex) { exception = ex; } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java index d42a183291..c47e7c0859 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java @@ -59,7 +59,7 @@ public int read() throws IOException { wire.input(b); } return b; - } catch (IOException ex) { + } catch (final IOException ex) { wire.input("[read] I/O error: " + ex.getMessage()); throw ex; } @@ -75,7 +75,7 @@ public int read(final byte[] b) throws IOException { wire.input(b, 0, bytesRead); } return bytesRead; - } catch (IOException ex) { + } catch (final IOException ex) { wire.input("[read] I/O error: " + ex.getMessage()); throw ex; } @@ -91,7 +91,7 @@ public int read(final byte[] b, final int off, final int len) throws IOException wire.input(b, off, bytesRead); } return bytesRead; - } catch (IOException ex) { + } catch (final IOException ex) { wire.input("[read] I/O error: " + ex.getMessage()); throw ex; } @@ -101,7 +101,7 @@ public int read(final byte[] b, final int off, final int len) throws IOException public long skip(final long n) throws IOException { try { return super.skip(n); - } catch (IOException ex) { + } catch (final IOException ex) { wire.input("[skip] I/O error: " + ex.getMessage()); throw ex; } @@ -111,7 +111,7 @@ public long skip(final long n) throws IOException { public int available() throws IOException { try { return in.available(); - } catch (IOException ex) { + } catch (final IOException ex) { wire.input("[available] I/O error : " + ex.getMessage()); throw ex; } @@ -136,7 +136,7 @@ public boolean markSupported() { public void close() throws IOException { try { in.close(); - } catch (IOException ex) { + } catch (final IOException ex) { wire.input("[close] I/O error: " + ex.getMessage()); throw ex; } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java index c70cb17005..b292453f4e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java @@ -53,7 +53,7 @@ public LoggingOutputStream(final OutputStream out, final Wire wire) { public void write(final int b) throws IOException { try { wire.output(b); - } catch (IOException ex) { + } catch (final IOException ex) { wire.output("[write] I/O error: " + ex.getMessage()); throw ex; } @@ -64,7 +64,7 @@ public void write(final byte[] b) throws IOException { try { wire.output(b); out.write(b); - } catch (IOException ex) { + } catch (final IOException ex) { wire.output("[write] I/O error: " + ex.getMessage()); throw ex; } @@ -75,7 +75,7 @@ public void write(final byte[] b, final int off, final int len) throws IOExcepti try { wire.output(b, off, len); out.write(b, off, len); - } catch (IOException ex) { + } catch (final IOException ex) { wire.output("[write] I/O error: " + ex.getMessage()); throw ex; } @@ -85,7 +85,7 @@ public void write(final byte[] b, final int off, final int len) throws IOExcepti public void flush() throws IOException { try { out.flush(); - } catch (IOException ex) { + } catch (final IOException ex) { wire.output("[flush] I/O error: " + ex.getMessage()); throw ex; } @@ -95,7 +95,7 @@ public void flush() throws IOException { public void close() throws IOException { try { out.close(); - } catch (IOException ex) { + } catch (final IOException ex) { wire.output("[close] I/O error: " + ex.getMessage()); throw ex; } diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java index 054ee90d11..1c6914a6ec 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java @@ -78,7 +78,7 @@ protected AbstractCookieSpec(final HashMap map) protected AbstractCookieSpec(final CommonCookieAttributeHandler... handlers) { super(); this.attribHandlerMap = new ConcurrentHashMap(handlers.length); - for (CommonCookieAttributeHandler handler: handlers) { + for (final CommonCookieAttributeHandler handler: handlers) { this.attribHandlerMap.put(handler.getAttributeName(), handler); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java index de00b6bfd8..82e891c980 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java @@ -153,7 +153,7 @@ public void parse(final SetCookie cookie, final String value) throws MalformedCo } } } - } catch (NumberFormatException ignore) { + } catch (final NumberFormatException ignore) { throw new MalformedCookieException("Invalid 'expires' attribute: " + value); } if (!foundTime || !foundDayOfMonth || !foundMonth || !foundYear) { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java index c9f9b99d30..22d7d1dbd3 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java @@ -84,7 +84,7 @@ protected RFC6265CookieSpec(final CommonCookieAttributeHandler... handlers) { super(); this.attribHandlers = handlers.clone(); this.attribHandlerMap = new ConcurrentHashMap(handlers.length); - for (CommonCookieAttributeHandler handler: handlers) { + for (final CommonCookieAttributeHandler handler: handlers) { this.attribHandlerMap.put(handler.getAttributeName().toLowerCase(Locale.ROOT), handler); } this.tokenParser = TokenParser.INSTANCE; @@ -172,7 +172,7 @@ public final List parse(final Header header, final CookieOrigin origin) attribMap.remove(ClientCookie.EXPIRES_ATTR); } - for (Map.Entry entry: attribMap.entrySet()) { + for (final Map.Entry entry: attribMap.entrySet()) { final String paramName = entry.getKey(); final String paramValue = entry.getValue(); final CookieAttributeHandler handler = this.attribHandlerMap.get(paramName); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java index 7f2c42d35f..5955cbede3 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java @@ -100,10 +100,10 @@ public void writeTo(final OutputStream outstream) throws IOException { try { this.wrappedEntity.writeTo(outstream); releaseConnection(); - } catch (IOException ex) { + } catch (final IOException ex) { abortConnection(); throw ex; - } catch (RuntimeException ex) { + } catch (final RuntimeException ex) { abortConnection(); throw ex; } finally { @@ -118,10 +118,10 @@ public boolean eofDetected(final InputStream wrapped) throws IOException { // reading trailers after the response body: wrapped.close(); releaseConnection(); - } catch (IOException ex) { + } catch (final IOException ex) { abortConnection(); throw ex; - } catch (RuntimeException ex) { + } catch (final RuntimeException ex) { abortConnection(); throw ex; } finally { @@ -144,10 +144,10 @@ public boolean streamClosed(final InputStream wrapped) throws IOException { throw ex; } } - } catch (IOException ex) { + } catch (final IOException ex) { abortConnection(); throw ex; - } catch (RuntimeException ex) { + } catch (final RuntimeException ex) { abortConnection(); throw ex; } finally { diff --git a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java index adc53403f4..f7008b88d7 100644 --- a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java +++ b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java @@ -74,7 +74,7 @@ public void testCompressionIOExceptionLeavesOutputStreamOpen() throws Exception final OutputStream out = Mockito.mock(OutputStream.class); try { gzipe.writeTo(out); - } catch (IOException ex) { + } catch (final IOException ex) { Mockito.verify(out, Mockito.never()).close(); } } diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java b/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java index 2d94e7ab61..79fc981a6c 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java @@ -264,7 +264,7 @@ public void testHTTPCLIENT_1316() throws Exception{ try { DefaultHostnameVerifier.matchIPv6Address(host1, Arrays.asList("2001:0db8:aaaa:bbbb:cccc::10")); Assert.fail("SSLException expected"); - } catch (SSLException expected) { + } catch (final SSLException expected) { } final String host2 = "2001:0db8:aaaa:bbbb:cccc::1"; DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList("2001:0db8:aaaa:bbbb:cccc:0:0:0001")); @@ -272,7 +272,7 @@ public void testHTTPCLIENT_1316() throws Exception{ try { DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList("2001:0db8:aaaa:bbbb:cccc::10")); Assert.fail("SSLException expected"); - } catch (SSLException expected) { + } catch (final SSLException expected) { } } @@ -289,12 +289,12 @@ public void testExtractCN() throws Exception { try { DefaultHostnameVerifier.extractCN("blah,blah"); Assert.fail("SSLException expected"); - } catch (SSLException expected) { + } catch (final SSLException expected) { } try { DefaultHostnameVerifier.extractCN("cn,o=blah"); Assert.fail("SSLException expected"); - } catch (SSLException expected) { + } catch (final SSLException expected) { } } diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java b/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java index 3fd282ad62..a04d9d6bc9 100644 --- a/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java +++ b/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java @@ -97,7 +97,7 @@ public FormBodyPart build() { Asserts.notNull(this.body, "Content body"); final Header headerCopy = new Header(); final List fields = this.header.getFields(); - for (MinimalField field: fields) { + for (final MinimalField field: fields) { headerCopy.addField(field); } if (headerCopy.getField(MIME.CONTENT_DISPOSITION) == null) { From d730041f0a40fc0ad963f6fede13f96ade2896ca Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 5 Feb 2016 04:53:53 +0000 Subject: [PATCH 053/204] Javadoc typo. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1728602 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/java/org/apache/http/client/fluent/Content.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java index 2be4c3f60f..52b1db7edf 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java @@ -34,7 +34,7 @@ import org.apache.http.entity.ContentType; /** - * This class represents arbitrary content of a specfic type that can be consumed + * This class represents arbitrary content of a specific type that can be consumed * multiple times and requires no explicit deallocation. */ public class Content { From 3cde2e432df15a2e7263feece3e223318e7db018 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 6 Feb 2016 03:09:01 +0000 Subject: [PATCH 054/204] [HTTPCLIENT-1717] Make fluent API .Content.Content(byte[], ContentType) public. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1728787 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 2 ++ .../src/main/java/org/apache/http/client/fluent/Content.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 30cc6af3dc..80fc9e06da 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -14,6 +14,8 @@ Changelog: * [HTTPCLIENT-1715] NTLMEngineImpl.Type1Message not thread safe but declared as a constant. Contributed by Olivier Lafontaine , Gary Gregory +* [HTTPCLIENT-1717] Make fluent API .Content.Content(byte[], ContentType) public. + Contributed by Cash Costello Release 4.5.1 ------------------- diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java index 52b1db7edf..87167c0bb1 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Content.java @@ -44,7 +44,7 @@ public class Content { private final byte[] raw; private final ContentType type; - Content(final byte[] raw, final ContentType type) { + public Content(final byte[] raw, final ContentType type) { super(); this.raw = raw; this.type = type; From 96c4a550291bfaf4aae8de755e59493f5ea3e5e9 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 17 Feb 2016 13:54:29 +0000 Subject: [PATCH 055/204] HTTPCLIENT-1718, HTTPCLEINT-1719: credentials fix to allow proxy authetication Contributed by 212427891 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1730836 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/osgi/impl/OSGiCredentialsProvider.java | 6 ++---- .../org/apache/http/osgi/impl/OSGiProxyConfiguration.java | 2 +- .../apache/http/osgi/impl/OSGiProxyConfigurationTest.java | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java index f2af640114..e9d6e51471 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java @@ -72,11 +72,9 @@ public Credentials getCredentials(final AuthScope authscope) { final ProxyConfiguration proxyConfiguration = (ProxyConfiguration) proxyConfigurationObject; if (proxyConfiguration.isEnabled()) { final AuthScope actual = new AuthScope(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); - if (authscope.equals(actual)) { - return new UsernamePasswordCredentials(proxyConfiguration.getUsername(), - proxyConfiguration.getPassword()); + if (authscope.match(actual) >= 12) { + return new UsernamePasswordCredentials(proxyConfiguration.getUsername(), proxyConfiguration.getPassword()); } - } } } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java index 00ae3a0be8..a132c735ad 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiProxyConfiguration.java @@ -63,7 +63,7 @@ public final class OSGiProxyConfiguration implements ProxyConfiguration { /** * Property representing the username to authenticate with towards the proxy. Defaults to empty. */ - private static final String PROPERTYNAME_PROXY_USERNAME = "proxy.username"; + private static final String PROPERTYNAME_PROXY_USERNAME = "proxy.user"; private static final String PROPERTYDEFAULT_PROXY_USERNAME = ""; diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java index 55b117497a..57505f6b2e 100644 --- a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiProxyConfigurationTest.java @@ -43,7 +43,7 @@ public void testToString() { config.put("proxy.enabled", false); config.put("proxy.host", "h"); config.put("proxy.port", 1); - config.put("proxy.username", "u"); + config.put("proxy.user", "u"); config.put("proxy.password", "p"); config.put("proxy.exceptions", new String[]{"e"}); From 04fb7e6d8e2aef7ae4465b26a931deffb9775450 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 19 Feb 2016 23:33:14 +0000 Subject: [PATCH 056/204] [HTTPCLIENT-1665] Regression in org.apache.http.entity.mime.MultipartEntity and org.apache.http.entity.mime.content.StringBody. Use ASCII when charset is null. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1731313 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/entity/mime/content/StringBody.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/content/StringBody.java b/httpmime/src/main/java/org/apache/http/entity/mime/content/StringBody.java index 535ce4b28d..1bfbac2c38 100644 --- a/httpmime/src/main/java/org/apache/http/entity/mime/content/StringBody.java +++ b/httpmime/src/main/java/org/apache/http/entity/mime/content/StringBody.java @@ -110,7 +110,7 @@ public StringBody( final String text, final String mimeType, final Charset charset) throws UnsupportedEncodingException { - this(text, ContentType.create(mimeType, charset)); + this(text, ContentType.create(mimeType, charset != null ? charset : Consts.ASCII)); } /** From 600b4cadf33d187ae179e333fef2cf6d88186adb Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 21 Feb 2016 13:28:24 +0000 Subject: [PATCH 057/204] Javadoc fix git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1731528 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/impl/client/HttpClientBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 5dd61624e4..dab3ab1353 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -614,7 +614,7 @@ public final HttpClientBuilder setHttpProcessor(final HttpProcessor httpprocesso /** * Assigns {@link DnsResolver} instance. - *

+ *

* Please note this value can be overridden by the {@link #setConnectionManager(HttpClientConnectionManager)} method. */ public final HttpClientBuilder setDnsResolver(final DnsResolver dnsResolver) { From 1c7ce797221ec8174d91f58432324a1ac03e29d7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 21 Feb 2016 13:28:43 +0000 Subject: [PATCH 058/204] Updated release notes for HttpClient 4.5.2 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1731529 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 80fc9e06da..a5ba811358 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -8,14 +8,45 @@ Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- -* [HTTPCLIENT-1714] Add HttpClientBuilder.setDnsResolver(DnsResolver). - Contributed by Alexis Thaveau +* [HTTPCLIENT-1710, HTTPCLIENT-1718, HTTPCLEINT-1719] OSGi container compatibility improvements. + Contributed by 212427891 + +* [HTTPCLIENT-1717] Make fluent API Content#Content(byte[], ContentType) public. + Contributed by Cash Costello -* [HTTPCLIENT-1715] NTLMEngineImpl.Type1Message not thread safe but declared as a constant. +* [HTTPCLIENT-1715] NTLMEngineImpl#Type1Message not thread safe but declared as a constant. Contributed by Olivier Lafontaine , Gary Gregory -* [HTTPCLIENT-1717] Make fluent API .Content.Content(byte[], ContentType) public. - Contributed by Cash Costello +* [HTTPCLIENT-1714] Add HttpClientBuilder#setDnsResolver(DnsResolver). + Contributed by Alexis Thaveau + +* [HTTPCLIENT-1712] SPNego schemes to take service scheme into account when generating auth token. + Contributed by Georg Romstorfer + +* [HTTPCLIENT-1700] Netscape draft, browser compatibility, RFC 2109, RFC 2965 and default cookie + specs to ignore cookies with empty name for consistency with RFC 6265 specs. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1704] IgnoreSpec#match to always return false. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1550] Fixed 'deflate' zlib header check. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1698] Fixed matching of IPv6 addresses by DefaultHostnameVerifier + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1695] RFC 6265 compliant cookie spec to ignore cookies with empty name / missing + value. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1216] Removed ThreadLocal subclass from DateUtils. + Contributed by Jochen Kemnade + +* [HTTPCLIENT-1685] PublicSuffixDomainFilter to ignore local hosts and local domains. + Contributed by Oleg Kalnichevski + + Release 4.5.1 ------------------- From a29cda6687cdc436210235a9ea66f02ce96ed169 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 21 Feb 2016 15:35:37 +0000 Subject: [PATCH 059/204] Updated NOTICE.txt git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1731534 13f79535-47bb-0310-9956-ffa450edef68 --- NOTICE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE.txt b/NOTICE.txt index 6a8629b407..91e5c40c4c 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Apache HttpComponents Client -Copyright 1999-2015 The Apache Software Foundation +Copyright 1999-2016 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). From 2ee82b5d80c27f75b70eb97118ea8952e4b94c3b Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 21 Feb 2016 15:35:44 +0000 Subject: [PATCH 060/204] Upgraded HttpCore to version 4.4.4 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1731535 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 478ad22a4a..1e8e9bc9ce 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 1.6 1.6 - 4.4.3 + 4.4.4 1.2 1.9 2.6.9 From 85b0047f6e4e867cb1466e86e67c28c4b816bf0c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 26 Feb 2016 11:39:03 +0000 Subject: [PATCH 061/204] Upgraded HttpClient version to 4.5.3-SNAPSHOT git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1732457 13f79535-47bb-0310-9956-ffa450edef68 --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 10dea485d9..626a4e20b7 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.2-SNAPSHOT + 4.5.3-SNAPSHOT fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 480eba362a..4dd8fc16b7 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.2-SNAPSHOT + 4.5.3-SNAPSHOT httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index b6956cc7cb..29b585c5de 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.2-SNAPSHOT + 4.5.3-SNAPSHOT httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index 89c2cdb8f0..e19af78b69 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.2-SNAPSHOT + 4.5.3-SNAPSHOT httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 985f53db08..383ff60589 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.2-SNAPSHOT + 4.5.3-SNAPSHOT httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index 538e13703c..df073cc044 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.2-SNAPSHOT + 4.5.3-SNAPSHOT httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 1e8e9bc9ce..8a12f46eff 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.2-SNAPSHOT + 4.5.3-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 From 0cb0a3dea1eefcab6ce7114bac9efcf7020b6764 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 1 Mar 2016 22:36:44 +0000 Subject: [PATCH 062/204] Remove useless semicolon. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1733178 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 8539791992..e5bfa58e4b 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -64,7 +64,7 @@ @Immutable public final class DefaultHostnameVerifier implements HostnameVerifier { - enum TYPE { IPv4, IPv6, DNS }; + enum TYPE { IPv4, IPv6, DNS } final static int DNS_NAME_TYPE = 2; final static int IP_ADDRESS_TYPE = 7; From 5a60e7f94829653c9e73cee3a91b55d67891c75d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 1 Mar 2016 22:40:20 +0000 Subject: [PATCH 063/204] Comment empty blocks. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1733179 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index e5bfa58e4b..360b7b3aad 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -263,7 +263,9 @@ static String extractCN(final String subjectPrincipal) throws SSLException { return value.toString(); } } catch (final NoSuchElementException ignore) { + // ignore exception, why? } catch (final NamingException ignore) { + // ignore exception, why? } } } @@ -278,6 +280,7 @@ static List extractSubjectAlts(final X509Certificate cert, final int sub try { c = cert.getSubjectAlternativeNames(); } catch(final CertificateParsingException ignore) { + // ignore exception, why? } List subjectAltList = null; if (c != null) { From 7663e6a596841122cedfbfd15754843b2d755427 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 2 Mar 2016 20:47:19 +0000 Subject: [PATCH 064/204] HTTPCLIENT-1726: Copy the SNI fix from SSLConnectionSocketFactory to the deprecated SSLSocketFactory class. Signed-off-by: David Black git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1733362 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/conn/ssl/SSLSocketFactory.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java index 37f539c541..03fbe68017 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java @@ -39,6 +39,7 @@ import java.security.SecureRandom; import java.security.UnrecoverableKeyException; +import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; @@ -519,9 +520,7 @@ private void internalPrepareSocket(final SSLSocket socket) throws IOException { @Override public Socket createSocket(final HttpContext context) throws IOException { - final SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); - internalPrepareSocket(sock); - return sock; + return SocketFactory.getDefault().createSocket(); } @Override From eda8dc5d32657203f576fb748f2092ff02c668c4 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 3 Mar 2016 01:59:34 +0000 Subject: [PATCH 065/204] [HTTPCLIENT-1727] org.apache.http.impl.client.AbstractHttpClient#createClientConnectionManager Does not account for context class loader. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1733406 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 14 ++++++++++++++ .../http/impl/client/AbstractHttpClient.java | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index a5ba811358..20d2e68d13 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,17 @@ +Release 4.5.3 +------------------- + +HttpClient 4.5.3 (GA) is a maintenance release that fixes a number of minor defects found since 4.5.2. + +Please note that as of 4.4 HttpClient requires Java 1.6 or newer. + +Changelog: +------------------- + +* [HTTPCLIENT-1727] org.apache.http.impl.client.AbstractHttpClient#createClientConnectionManager Does not account for context class loader. + Contributed by Charles Allen + + Release 4.5.2 ------------------- diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java index 18a42d727d..f64fa8bb0b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java @@ -327,9 +327,15 @@ protected ClientConnectionManager createClientConnectionManager() { final String className = (String) params.getParameter( ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME); + final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); if (className != null) { try { - final Class clazz = Class.forName(className); + final Class clazz; + if (contextLoader != null) { + clazz = Class.forName(className, true, contextLoader); + } else { + clazz = Class.forName(className); + } factory = (ClientConnectionManagerFactory) clazz.newInstance(); } catch (final ClassNotFoundException ex) { throw new IllegalStateException("Invalid class name: " + className); From 8f3829334d10ef45c1fe2ff267c340251effe5ec Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 7 Mar 2016 13:52:07 +0000 Subject: [PATCH 066/204] HTTPCLIENT-1729: javadoc fix git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1733927 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/conn/PoolingHttpClientConnectionManager.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java index ce5de25450..267818cbcd 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java @@ -54,8 +54,8 @@ import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.HttpClientConnectionOperator; import org.apache.http.conn.HttpConnectionFactory; -import org.apache.http.conn.SchemePortResolver; import org.apache.http.conn.ManagedHttpClientConnection; +import org.apache.http.conn.SchemePortResolver; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; @@ -88,8 +88,7 @@ * Previously, the code would check every connection by default before re-using it. * The code now only checks the connection if the elapsed time since * the last use of the connection exceeds the timeout that has been set. - * The default timeout is set to 5000ms - see - * {@link #PoolingHttpClientConnectionManager(HttpClientConnectionOperator, HttpConnectionFactory, long, TimeUnit)} + * The default timeout is set to 2000ms *

* * @since 4.3 From 1b41b52b1481067dab5672bc5c1161adc4558b06 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 15 Mar 2016 15:26:32 +0000 Subject: [PATCH 067/204] Revert "HTTPCLIENT-1712: SPNego schemes to take service scheme into account when generating auth token" This reverts commit 1d50c1a1a16ee6f9c5930d966f1b234d98bf261f. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1735108 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/impl/auth/GGSSchemeBase.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java index ffb22b023e..e4df5803b5 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java @@ -28,7 +28,6 @@ import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.Locale; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; @@ -80,7 +79,6 @@ enum State { /** base64 decoded challenge **/ private byte[] token; - private String service; GGSSchemeBase(final boolean stripPort, final boolean useCanonicalHostname) { super(); @@ -118,7 +116,7 @@ protected byte[] generateGSSToken( inputBuff = new byte[0]; } final GSSManager manager = getManager(); - final GSSName serverName = manager.createName(service + "@" + authServer, GSSName.NT_HOSTBASED_SERVICE); + final GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE); final GSSCredential gssCredential; if (credentials instanceof KerberosCredentials) { @@ -214,8 +212,6 @@ public Header authenticate( authServer = hostname + ":" + host.getPort(); } - service = host.getSchemeName().toUpperCase(Locale.ROOT); - if (log.isDebugEnabled()) { log.debug("init " + authServer); } From 7e38f831d5b43f5aa7de94387a024e905e5a1cce Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 22 Mar 2016 14:05:37 +0000 Subject: [PATCH 068/204] HTTPCLIENT-1730: javadoc improvements git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1736192 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/conn/PoolingHttpClientConnectionManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java index 267818cbcd..e5ee721e7a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java @@ -84,6 +84,11 @@ * can be adjusted using {@link ConnPoolControl} methods. *

*

+ * Total time to live (TTL) set at construction time defines maximum life span + * of persistent connections regardless of their expiration setting. No persistent + * connection will be re-used past its TTL value. + *

+ *

* The handling of stale connections was changed in version 4.4. * Previously, the code would check every connection by default before re-using it. * The code now only checks the connection if the elapsed time since From cbf517ace6588ed532e28e8099ad7e95f50af4e5 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 2 Apr 2016 10:26:41 +0000 Subject: [PATCH 069/204] HTTPCLIENT-1732: SystemDefaultCredentialsProvider to take http.proxyHost and http.proxyPort system properties into account git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1737485 13f79535-47bb-0310-9956-ffa450edef68 --- .../SystemDefaultCredentialsProvider.java | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index 69c4fde41c..debe142fa7 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -111,12 +111,30 @@ public Credentials getCredentials(final AuthScope authscope) { if (localcreds != null) { return localcreds; } - if (authscope.getHost() != null) { - PasswordAuthentication systemcreds = getSystemCreds( - authscope, Authenticator.RequestorType.SERVER); + final String host = authscope.getHost(); + if (host != null) { + PasswordAuthentication systemcreds = getSystemCreds(authscope, Authenticator.RequestorType.SERVER); if (systemcreds == null) { - systemcreds = getSystemCreds( - authscope, Authenticator.RequestorType.PROXY); + systemcreds = getSystemCreds(authscope, Authenticator.RequestorType.PROXY); + } + if (systemcreds == null) { + final String proxyHost = System.getProperty("http.proxyHost"); + if (proxyHost != null) { + final String proxyPort = System.getProperty("http.proxyPort"); + if (proxyPort != null) { + try { + final AuthScope systemScope = new AuthScope(proxyHost, Integer.parseInt(proxyPort)); + if (authscope.match(systemScope) >= 0) { + final String proxyUser = System.getProperty("http.proxyUser"); + if (proxyUser != null) { + final String proxyPassword = System.getProperty("http.proxyPassword"); + systemcreds = new PasswordAuthentication(proxyUser, proxyPassword != null ? proxyPassword.toCharArray() : new char[] {}); + } + } + } catch (NumberFormatException ex) { + } + } + } } if (systemcreds != null) { final String domain = System.getProperty("http.auth.ntlm.domain"); From 951d6d1bfd187c86c01e5d797e86f1aa12f5dae0 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 28 May 2016 17:01:12 +0000 Subject: [PATCH 070/204] HTTPCLIENT-1744: normalize hostname and certificate CN when matching to CN git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1745908 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/conn/ssl/DefaultHostnameVerifier.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 360b7b3aad..eb1f653727 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -176,7 +176,9 @@ static void matchDNSName(final String host, final List subjectAlts, static void matchCN(final String host, final String cn, final PublicSuffixMatcher publicSuffixMatcher) throws SSLException { - if (!matchIdentityStrict(host, cn, publicSuffixMatcher)) { + final String normalizedHost = host.toLowerCase(Locale.ROOT); + final String normalizedCn = cn.toLowerCase(Locale.ROOT); + if (!matchIdentityStrict(normalizedHost, normalizedCn, publicSuffixMatcher)) { throw new SSLException("Certificate for <" + host + "> doesn't match " + "common name of the certificate subject: " + cn); } From b52a623ccfefb66d03cd8cb068d1fdce2e6f8da2 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 28 May 2016 17:02:01 +0000 Subject: [PATCH 071/204] Cleaned up comments git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1745909 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/http/conn/ssl/DefaultHostnameVerifier.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index eb1f653727..299e7a7664 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -265,9 +265,9 @@ static String extractCN(final String subjectPrincipal) throws SSLException { return value.toString(); } } catch (final NoSuchElementException ignore) { - // ignore exception, why? + // ignore exception } catch (final NamingException ignore) { - // ignore exception, why? + // ignore exception } } } @@ -282,7 +282,7 @@ static List extractSubjectAlts(final X509Certificate cert, final int sub try { c = cert.getSubjectAlternativeNames(); } catch(final CertificateParsingException ignore) { - // ignore exception, why? + return null; } List subjectAltList = null; if (c != null) { From 572fd4cd9c43ff4dde3751799966115efff5e582 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 3 Jun 2016 19:21:14 +0000 Subject: [PATCH 072/204] HTTPCLIENT-1736: do not request cred delegation by default when using Kerberos auth git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1746747 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/auth/SpnegoTokenGenerator.java | 2 +- .../apache/http/impl/auth/GGSSchemeBase.java | 25 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/SpnegoTokenGenerator.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/SpnegoTokenGenerator.java index 23e380498d..50ff980b6b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/SpnegoTokenGenerator.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/auth/SpnegoTokenGenerator.java @@ -37,7 +37,7 @@ * @since 4.1 * * @deprecated (4.2) subclass {@link KerberosScheme} and override - * {@link KerberosScheme#generateGSSToken(byte[], org.ietf.jgss.Oid, String)} + * {@link KerberosScheme#generateGSSToken(byte[], org.ietf.jgss.Oid, String, org.apache.http.auth.Credentials)} */ @Deprecated public interface SpnegoTokenGenerator { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java index e4df5803b5..d9e008f402 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java @@ -111,10 +111,6 @@ protected byte[] generateGSSToken( protected byte[] generateGSSToken( final byte[] input, final Oid oid, final String authServer, final Credentials credentials) throws GSSException { - byte[] inputBuff = input; - if (inputBuff == null) { - inputBuff = new byte[0]; - } final GSSManager manager = getManager(); final GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE); @@ -125,13 +121,24 @@ protected byte[] generateGSSToken( gssCredential = null; } - final GSSContext gssContext = manager.createContext( - serverName.canonicalize(oid), oid, gssCredential, GSSContext.DEFAULT_LIFETIME); - gssContext.requestMutualAuth(true); - gssContext.requestCredDeleg(true); - return gssContext.initSecContext(inputBuff, 0, inputBuff.length); + final GSSContext gssContext = createGSSContext(manager, oid, serverName, gssCredential); + if (input != null) { + return gssContext.initSecContext(input, 0, input.length); + } else { + return gssContext.initSecContext(new byte[] {}, 0, 0); + } } + GSSContext createGSSContext( + final GSSManager manager, + final Oid oid, + final GSSName serverName, + final GSSCredential gssCredential) throws GSSException { + final GSSContext gssContext = manager.createContext(serverName.canonicalize(oid), oid, gssCredential, + GSSContext.DEFAULT_LIFETIME); + gssContext.requestMutualAuth(true); + return gssContext; + } /** * @deprecated (4.4) Use {@link #generateToken(byte[], String, org.apache.http.auth.Credentials)}. */ From 324218e8e6b508f74987c74c99b912b3ca8a1a8d Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 3 Jun 2016 19:30:30 +0000 Subject: [PATCH 073/204] HTTPCLIENT-1746: improved argument validation in URLEncodedUtils git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1746749 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/client/fluent/Request.java | 2 +- .../http/client/utils/URLEncodedUtils.java | 22 +++++++++++++++--- .../client/utils/TestURLEncodedUtils.java | 23 ++++++++++--------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java index 593cee8a41..1d2de2e736 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java @@ -357,7 +357,7 @@ public Request bodyForm(final Iterable formParams, fin paramList.add(param); } final ContentType contentType = ContentType.create(URLEncodedUtils.CONTENT_TYPE, charset); - final String s = URLEncodedUtils.format(paramList, charset != null ? charset.name() : null); + final String s = URLEncodedUtils.format(paramList, charset); return bodyString(s, contentType); } diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index de18e6d58e..adc81c715b 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -72,6 +72,13 @@ public class URLEncodedUtils { private static final char QP_SEP_S = ';'; private static final String NAME_VALUE_SEPARATOR = "="; + /** + * @deprecated 4.5 Use {@link #parse(URI, Charset)} + */ + public static List parse(final URI uri, final String charsetName) { + return parse(uri, charsetName != null ? Charset.forName(charsetName) : null); + } + /** * Returns a list of {@link NameValuePair NameValuePairs} as built from the URI's query portion. For example, a URI * of {@code http://example.org/path/to/file?a=1&b=2&c=3} would return a list of three NameValuePairs, one for a=1, @@ -84,13 +91,16 @@ public class URLEncodedUtils { * @param uri * URI to parse * @param charset - * Charset name to use while parsing the query + * Charset to use while parsing the query * @return a list of {@link NameValuePair} as built from the URI's query portion. + * + * @since 4.5 */ - public static List parse(final URI uri, final String charset) { + public static List parse(final URI uri, final Charset charset) { + Args.notNull(uri, "URI"); final String query = uri.getRawQuery(); if (query != null && !query.isEmpty()) { - return parse(query, Charset.forName(charset)); + return parse(query, charset); } return Collections.emptyList(); } @@ -109,6 +119,7 @@ public static List parse(final URI uri, final String charset) { */ public static List parse( final HttpEntity entity) throws IOException { + Args.notNull(entity, "HTTP entity"); final ContentType contentType = ContentType.get(entity); if (contentType == null || !contentType.getMimeType().equalsIgnoreCase(CONTENT_TYPE)) { return Collections.emptyList(); @@ -144,6 +155,7 @@ public static List parse( * {@code application/x-www-form-urlencoded}. */ public static boolean isEncoded(final HttpEntity entity) { + Args.notNull(entity, "HTTP entity"); final Header h = entity.getContentType(); if (h != null) { final HeaderElement[] elems = h.getElements(); @@ -232,6 +244,9 @@ public static void parse( * @since 4.2 */ public static List parse(final String s, final Charset charset) { + if (s == null) { + return Collections.emptyList(); + } final CharArrayBuffer buffer = new CharArrayBuffer(s.length()); buffer.append(s); return parse(buffer, charset, QP_SEP_A, QP_SEP_S); @@ -384,6 +399,7 @@ public static String format( final Iterable parameters, final char parameterSeparator, final Charset charset) { + Args.notNull(parameters, "Parameters"); final StringBuilder result = new StringBuilder(); for (final NameValuePair parameter : parameters) { final String encodedName = encodeFormFields(parameter.getName(), charset); diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java index 60d1eafedd..5c95402d51 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java @@ -28,6 +28,7 @@ package org.apache.http.client.utils; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -350,46 +351,46 @@ public void testFormat() throws Exception { @Test public void testFormatString() throws Exception { // as above, using String final List params = new ArrayList (); - Assert.assertEquals(0, URLEncodedUtils.format(params, "US-ASCII").length()); + Assert.assertEquals(0, URLEncodedUtils.format(params, StandardCharsets.US_ASCII).length()); params.clear(); params.add(new BasicNameValuePair("Name0", null)); - Assert.assertEquals("Name0", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name0", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name1", "Value1")); - Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name2", "")); - Assert.assertEquals("Name2=", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name2=", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name4", "Value 4&")); - Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name4", "Value+4&")); - Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name4", "Value 4& =4")); - Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name5", "aaa")); params.add(new BasicNameValuePair("Name6", "bbb")); - Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name7", "aaa")); params.add(new BasicNameValuePair("Name7", "b,b")); params.add(new BasicNameValuePair("Name7", "ccc")); - Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); params.clear(); params.add(new BasicNameValuePair("Name8", "xx, yy ,zz")); - Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, "US-ASCII")); + Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); } private List parse (final String params) { @@ -397,7 +398,7 @@ private List parse (final String params) { } private List parseString (final String uri) throws Exception { - return URLEncodedUtils.parse(new URI("?"+uri), "UTF-8"); + return URLEncodedUtils.parse(new URI("?"+uri), StandardCharsets.UTF_8); } private static void assertNameValuePair ( From b9ffaad9c714384ffb52f9a2a90105ea44447540 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 3 Jun 2016 19:43:48 +0000 Subject: [PATCH 074/204] Override LaxRedirectStrategy's INSTANCE field Surprisingly LaxRedirectStrategy.INSTANCE returns the instance of DefaultRedirectStrategy. Override the INSTANCE field to return LaxRedirectStrategy instead. Also add unit tests to LaxRedirectStrategy. Contributed by Eric Wu git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1746752 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/client/LaxRedirectStrategy.java | 4 +- .../impl/client/TestLaxRedirectStrategy.java | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 httpclient/src/test/java/org/apache/http/impl/client/TestLaxRedirectStrategy.java diff --git a/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java index 04aa87fd2e..8e7ba7e24d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java @@ -35,7 +35,7 @@ /** * Lax {@link org.apache.http.client.RedirectStrategy} implementation - * that automatically redirects all HEAD, GET and POST requests. + * that automatically redirects all HEAD, GET, POST, and DELETE requests. * This strategy relaxes restrictions on automatic redirection of * POST methods imposed by the HTTP specification. * @@ -44,6 +44,8 @@ @Immutable public class LaxRedirectStrategy extends DefaultRedirectStrategy { + public static final LaxRedirectStrategy INSTANCE = new LaxRedirectStrategy(); + /** * Redirectable methods. */ diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestLaxRedirectStrategy.java b/httpclient/src/test/java/org/apache/http/impl/client/TestLaxRedirectStrategy.java new file mode 100644 index 0000000000..f446fbfd64 --- /dev/null +++ b/httpclient/src/test/java/org/apache/http/impl/client/TestLaxRedirectStrategy.java @@ -0,0 +1,56 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.client; + +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.junit.Assert; +import org.junit.Test; + +public class TestLaxRedirectStrategy { + + @Test + public void testIsRedirectable() { + assertLaxRedirectable(new LaxRedirectStrategy()); + } + + @Test + public void testInstance() { + assertLaxRedirectable(LaxRedirectStrategy.INSTANCE); + } + + private void assertLaxRedirectable(final LaxRedirectStrategy redirectStrategy) { + Assert.assertTrue(redirectStrategy.isRedirectable(HttpGet.METHOD_NAME)); + Assert.assertTrue(redirectStrategy.isRedirectable(HttpHead.METHOD_NAME)); + Assert.assertFalse(redirectStrategy.isRedirectable(HttpPut.METHOD_NAME)); + Assert.assertTrue(redirectStrategy.isRedirectable(HttpPost.METHOD_NAME)); + Assert.assertTrue(redirectStrategy.isRedirectable(HttpDelete.METHOD_NAME)); + } +} From 5a9a842d23b520a19ff7011059fe54279e2446c4 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 10 Jun 2016 14:38:35 +0000 Subject: [PATCH 075/204] HTTPCLIENT-1747: apply RequestConfig defaults when using HttpParams values in backward compatibility mode git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1747724 13f79535-47bb-0310-9956-ffa450edef68 --- .../client/params/HttpClientParamConfig.java | 60 ++++++++++++------- .../http/impl/client/InternalHttpClient.java | 4 +- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/params/HttpClientParamConfig.java b/httpclient/src/main/java/org/apache/http/client/params/HttpClientParamConfig.java index 0b03917218..20160d47de 100644 --- a/httpclient/src/main/java/org/apache/http/client/params/HttpClientParamConfig.java +++ b/httpclient/src/main/java/org/apache/http/client/params/HttpClientParamConfig.java @@ -51,38 +51,54 @@ private HttpClientParamConfig() { @SuppressWarnings("unchecked") public static RequestConfig getRequestConfig(final HttpParams params) { - return RequestConfig.custom() + return getRequestConfig(params, RequestConfig.DEFAULT); + } + + @SuppressWarnings("unchecked") + public static RequestConfig getRequestConfig(final HttpParams params, final RequestConfig defaultConfig) { + final RequestConfig.Builder builder = RequestConfig.copy(defaultConfig) .setSocketTimeout(params.getIntParameter( - CoreConnectionPNames.SO_TIMEOUT, 0)) + CoreConnectionPNames.SO_TIMEOUT, defaultConfig.getSocketTimeout())) .setStaleConnectionCheckEnabled(params.getBooleanParameter( - CoreConnectionPNames.STALE_CONNECTION_CHECK, true)) + CoreConnectionPNames.STALE_CONNECTION_CHECK, defaultConfig.isStaleConnectionCheckEnabled())) .setConnectTimeout(params.getIntParameter( - CoreConnectionPNames.CONNECTION_TIMEOUT, 0)) + CoreConnectionPNames.CONNECTION_TIMEOUT, defaultConfig.getConnectTimeout())) .setExpectContinueEnabled(params.getBooleanParameter( - CoreProtocolPNames.USE_EXPECT_CONTINUE, false)) - .setProxy((HttpHost) params.getParameter( - ConnRoutePNames.DEFAULT_PROXY)) - .setLocalAddress((InetAddress) params.getParameter( - ConnRoutePNames.LOCAL_ADDRESS)) - .setProxyPreferredAuthSchemes((Collection) params.getParameter( - AuthPNames.PROXY_AUTH_PREF)) - .setTargetPreferredAuthSchemes((Collection) params.getParameter( - AuthPNames.TARGET_AUTH_PREF)) + CoreProtocolPNames.USE_EXPECT_CONTINUE, defaultConfig.isExpectContinueEnabled())) .setAuthenticationEnabled(params.getBooleanParameter( - ClientPNames.HANDLE_AUTHENTICATION, true)) + ClientPNames.HANDLE_AUTHENTICATION, defaultConfig.isAuthenticationEnabled())) .setCircularRedirectsAllowed(params.getBooleanParameter( - ClientPNames.ALLOW_CIRCULAR_REDIRECTS, false)) + ClientPNames.ALLOW_CIRCULAR_REDIRECTS, defaultConfig.isCircularRedirectsAllowed())) .setConnectionRequestTimeout((int) params.getLongParameter( - ClientPNames.CONN_MANAGER_TIMEOUT, 0)) - .setCookieSpec((String) params.getParameter( - ClientPNames.COOKIE_POLICY)) + ClientPNames.CONN_MANAGER_TIMEOUT, defaultConfig.getConnectionRequestTimeout())) .setMaxRedirects(params.getIntParameter( - ClientPNames.MAX_REDIRECTS, 50)) + ClientPNames.MAX_REDIRECTS, defaultConfig.getMaxRedirects())) .setRedirectsEnabled(params.getBooleanParameter( - ClientPNames.HANDLE_REDIRECTS, true)) + ClientPNames.HANDLE_REDIRECTS, defaultConfig.isRedirectsEnabled())) .setRelativeRedirectsAllowed(!params.getBooleanParameter( - ClientPNames.REJECT_RELATIVE_REDIRECT, false)) - .build(); + ClientPNames.REJECT_RELATIVE_REDIRECT, !defaultConfig.isRelativeRedirectsAllowed())); + + final HttpHost proxy = (HttpHost) params.getParameter(ConnRoutePNames.DEFAULT_PROXY); + if (proxy != null) { + builder.setProxy(proxy); + } + final InetAddress localAddress = (InetAddress) params.getParameter(ConnRoutePNames.LOCAL_ADDRESS); + if (localAddress != null) { + builder.setLocalAddress(localAddress); + } + final Collection targetAuthPrefs = (Collection) params.getParameter(AuthPNames.TARGET_AUTH_PREF); + if (targetAuthPrefs != null) { + builder.setTargetPreferredAuthSchemes(targetAuthPrefs); + } + final Collection proxySuthPrefs = (Collection) params.getParameter(AuthPNames.PROXY_AUTH_PREF); + if (proxySuthPrefs != null) { + builder.setProxyPreferredAuthSchemes(proxySuthPrefs); + } + final String cookiePolicy = (String) params.getParameter(ClientPNames.COOKIE_POLICY); + if (cookiePolicy != null) { + builder.setCookieSpec(cookiePolicy); + } + return builder.build(); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java index 32bb5e0e23..d49dfee7f8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java @@ -170,10 +170,10 @@ protected CloseableHttpResponse doExecute( final HttpParams params = request.getParams(); if (params instanceof HttpParamsNames) { if (!((HttpParamsNames) params).getNames().isEmpty()) { - config = HttpClientParamConfig.getRequestConfig(params); + config = HttpClientParamConfig.getRequestConfig(params, this.defaultConfig); } } else { - config = HttpClientParamConfig.getRequestConfig(params); + config = HttpClientParamConfig.getRequestConfig(params, this.defaultConfig); } } if (config != null) { From 900d96fbef9d84436fb660697f9ed597b21fdcf7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 11 Jun 2016 14:22:08 +0000 Subject: [PATCH 076/204] Fixed build breakage due to Java 1.6 incompatibility git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1747894 13f79535-47bb-0310-9956-ffa450edef68 --- .../client/utils/TestURLEncodedUtils.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java index 5c95402d51..b0111ca21d 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java @@ -28,7 +28,6 @@ package org.apache.http.client.utils; import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -351,46 +350,46 @@ public void testFormat() throws Exception { @Test public void testFormatString() throws Exception { // as above, using String final List params = new ArrayList (); - Assert.assertEquals(0, URLEncodedUtils.format(params, StandardCharsets.US_ASCII).length()); + Assert.assertEquals(0, URLEncodedUtils.format(params, Consts.ASCII).length()); params.clear(); params.add(new BasicNameValuePair("Name0", null)); - Assert.assertEquals("Name0", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name0", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name1", "Value1")); - Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name2", "")); - Assert.assertEquals("Name2=", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name2=", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name4", "Value 4&")); - Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name4", "Value+4&")); - Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name4", "Value 4& =4")); - Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name5", "aaa")); params.add(new BasicNameValuePair("Name6", "bbb")); - Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name7", "aaa")); params.add(new BasicNameValuePair("Name7", "b,b")); params.add(new BasicNameValuePair("Name7", "ccc")); - Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, Consts.ASCII)); params.clear(); params.add(new BasicNameValuePair("Name8", "xx, yy ,zz")); - Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, StandardCharsets.US_ASCII)); + Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, Consts.ASCII)); } private List parse (final String params) { @@ -398,7 +397,7 @@ private List parse (final String params) { } private List parseString (final String uri) throws Exception { - return URLEncodedUtils.parse(new URI("?"+uri), StandardCharsets.UTF_8); + return URLEncodedUtils.parse(new URI("?"+uri), Consts.UTF_8); } private static void assertNameValuePair ( From df95271189ddc5704a25727f376a650fac22c2aa Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 11 Jun 2016 15:54:42 +0000 Subject: [PATCH 077/204] HTTPCLIENT-1749: OSGi client builder to use weak references to track HttpClient instances Contributed by Justin Edelson git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1747903 13f79535-47bb-0310-9956-ffa450edef68 --- httpclient-osgi/pom.xml | 4 +- .../impl/HttpProxyConfigurationActivator.java | 7 +- .../http/osgi/impl/OSGiHttpClientBuilder.java | 7 +- .../org/apache/http/osgi/impl/WeakList.java | 122 ++++++++++++++++++ .../apache/http/osgi/impl/WeakListTest.java | 62 +++++++++ 5 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java create mode 100644 httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 29b585c5de..06703d3ebd 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -176,7 +176,9 @@ org.codehaus.mojo clirr-maven-plugin - true + + org/apache/http/osgi/** + diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index 6586601eaa..67ac4355bb 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -31,7 +31,6 @@ import java.util.Dictionary; import java.util.Hashtable; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -62,7 +61,11 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M private final Map registeredConfigurations = new LinkedHashMap(); - private final List trackedHttpClients = new LinkedList(); + private final List trackedHttpClients; + + public HttpProxyConfigurationActivator() { + trackedHttpClients = new WeakList(); + } /** * {@inheritDoc} diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilder.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilder.java index d8d89a55aa..69cdc3e38a 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilder.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilder.java @@ -26,6 +26,7 @@ */ package org.apache.http.osgi.impl; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -39,7 +40,7 @@ */ final class OSGiHttpClientBuilder extends HttpClientBuilder { - private final List trackedHttpClients; + private final Collection trackedHttpClients; public OSGiHttpClientBuilder( final BundleContext bundleContext, @@ -55,7 +56,9 @@ public OSGiHttpClientBuilder( @Override public CloseableHttpClient build() { final CloseableHttpClient httpClient = super.build(); - trackedHttpClients.add(httpClient); + synchronized (trackedHttpClients) { + trackedHttpClients.add(httpClient); + } return httpClient; } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java new file mode 100644 index 0000000000..59ee6fd7fe --- /dev/null +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java @@ -0,0 +1,122 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import java.lang.ref.WeakReference; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +/** + * Implementation of a list backed by WeakReference objects. + * This is not a general purpose list and is only meant to be used by this package. It cannot correctly manage null entries by design. + */ +class WeakList extends AbstractList { + + private final List> innerList; + + public WeakList() { + this.innerList = new ArrayList>(); + } + + @Override + public T get(final int index) { + return innerList.get(index).get(); + } + + @Override + public int size() { + checkReferences(); + return innerList.size(); + } + + @Override + public boolean add(final T t) { + return innerList.add(new WeakReference(t)); + } + + private void checkReferences() { + final ListIterator> references = innerList.listIterator(); + while (references.hasNext()) { + final WeakReference reference = references.next(); + if (reference.get() == null) { + references.remove(); + } + } + } + + @Override + public Iterator iterator() { + return new WeakIterator(innerList.iterator()); + } + + private class WeakIterator implements Iterator { + + private final Iterator> innerIterator; + + private WeakReference next; + + public WeakIterator(final Iterator> innerIterator) { + this.innerIterator = innerIterator; + fetchNext(); + } + + public boolean hasNext() { + return next != null; + } + + public T next() { + if (next != null) { + final T result = next.get(); + fetchNext(); + return result; + } else { + throw new NoSuchElementException(); + } + } + + private void fetchNext() { + while (innerIterator.hasNext()) { + final WeakReference ref = innerIterator.next(); + final T obj = ref.get(); + if (obj != null) { + next = ref; + return; + } + } + next = null; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + } +} diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java new file mode 100644 index 0000000000..a930fa41bc --- /dev/null +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java @@ -0,0 +1,62 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import org.junit.Test; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertEquals; + +public class WeakListTest { + + @Test + public void testWeakList() { + final WeakList list = new WeakList(); + list.add("hello"); + list.add(null); + + // null objects are seen as GC'd, so we only expect a size of 1 + assertEquals(1, list.size()); + + final Iterator it = list.iterator(); + assertTrue(it.hasNext()); + assertEquals("hello", it.next()); + assertFalse(it.hasNext()); + boolean thrown = false; + try { + it.next(); + } catch (NoSuchElementException e) { + thrown = true; + } + assertTrue(thrown); + } + +} \ No newline at end of file From 6e4a1bbbf1adc901feae9be8ba96d1aa154f3dc7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 11 Jun 2016 15:54:55 +0000 Subject: [PATCH 078/204] HTTPCLIENT-1750: OSGi support for CachingHttpClientBuilder Contributed by Justin Edelson git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1747904 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/HttpProxyConfigurationActivator.java | 30 +++++++-- .../impl/OSGiCachingClientBuilderFactory.java | 59 ++++++++++++++++++ .../impl/OSGiCachingHttpClientBuilder.java | 61 +++++++++++++++++++ .../CachingHttpClientBuilderFactory.java | 35 +++++++++++ 4 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java create mode 100644 httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java create mode 100644 httpclient-osgi/src/main/java/org/apache/http/osgi/services/CachingHttpClientBuilderFactory.java diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index 67ac4355bb..4216976b41 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -35,6 +35,7 @@ import java.util.Map; import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.osgi.services.CachingHttpClientBuilderFactory; import org.apache.http.osgi.services.HttpClientBuilderFactory; import org.apache.http.osgi.services.ProxyConfiguration; import org.osgi.framework.BundleActivator; @@ -49,9 +50,17 @@ */ public final class HttpProxyConfigurationActivator implements BundleActivator, ManagedServiceFactory { - private static final String SERVICE_FACTORY_NAME = "Apache HTTP Client Proxy Configuration Factory"; + private static final String PROXY_SERVICE_FACTORY_NAME = "Apache HTTP Client Proxy Configuration Factory"; - private static final String SERVICE_PID = "org.apache.http.proxyconfigurator"; + private static final String PROXY_SERVICE_PID = "org.apache.http.proxyconfigurator"; + + private static final String BUILDER_FACTORY_SERVICE_NAME = "Apache HTTP Client Client Factory"; + + private static final String BUILDER_FACTORY_SERVICE_PID = "org.apache.http.httpclientfactory"; + + private static final String CACHEABLE_BUILDER_FACTORY_SERVICE_NAME = "Apache HTTP Client Caching Client Factory"; + + private static final String CACHEABLE_BUILDER_FACTORY_SERVICE_PID = "org.apache.http.cachinghttpclientfactory"; private ServiceRegistration configurator; @@ -78,12 +87,25 @@ public void start(final BundleContext context) throws Exception { final Hashtable props = new Hashtable(); props.put(Constants.SERVICE_PID, getName()); props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR)); - props.put(Constants.SERVICE_DESCRIPTION, SERVICE_FACTORY_NAME); + props.put(Constants.SERVICE_DESCRIPTION, PROXY_SERVICE_FACTORY_NAME); configurator = context.registerService(ManagedServiceFactory.class.getName(), this, props); + + props.clear(); + props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID); + props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR)); + props.put(Constants.SERVICE_DESCRIPTION, BUILDER_FACTORY_SERVICE_NAME); clientFactory = context.registerService(HttpClientBuilderFactory.class.getName(), new OSGiClientBuilderFactory(context, registeredConfigurations, trackedHttpClients), props); + + props.clear(); + props.put(Constants.SERVICE_PID, CACHEABLE_BUILDER_FACTORY_SERVICE_PID); + props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR)); + props.put(Constants.SERVICE_DESCRIPTION, CACHEABLE_BUILDER_FACTORY_SERVICE_NAME); + clientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(), + new OSGiCachingClientBuilderFactory(context, registeredConfigurations, trackedHttpClients), + props); } /** @@ -123,7 +145,7 @@ public void stop(final BundleContext context) throws Exception { */ @Override public String getName() { - return SERVICE_PID; + return PROXY_SERVICE_PID; } /** diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java new file mode 100644 index 0000000000..c496120847 --- /dev/null +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java @@ -0,0 +1,59 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.cache.CachingHttpClientBuilder; +import org.apache.http.osgi.services.CachingHttpClientBuilderFactory; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import java.util.List; +import java.util.Map; + +class OSGiCachingClientBuilderFactory implements CachingHttpClientBuilderFactory { + + private final BundleContext bundleContext; + + private final Map registeredConfigurations; + + private final List trackedHttpClients; + + public OSGiCachingClientBuilderFactory( + final BundleContext bundleContext, + final Map registeredConfigurations, + final List trackedHttpClients) { + this.bundleContext = bundleContext; + this.registeredConfigurations = registeredConfigurations; + this.trackedHttpClients = trackedHttpClients; + } + + @Override + public CachingHttpClientBuilder newBuilder() { + return new OSGiCachingHttpClientBuilder(bundleContext, registeredConfigurations, trackedHttpClients); + } +} diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java new file mode 100644 index 0000000000..57adae5f2d --- /dev/null +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java @@ -0,0 +1,61 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.cache.CachingHttpClientBuilder; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import java.util.List; +import java.util.Map; + +final class OSGiCachingHttpClientBuilder extends CachingHttpClientBuilder { + + private final List trackedHttpClients; + + public OSGiCachingHttpClientBuilder( + final BundleContext bundleContext, + final Map registeredConfigurations, + final List trackedHttpClients) { + this.trackedHttpClients = trackedHttpClients; + setDefaultCredentialsProvider( + new OSGiCredentialsProvider(bundleContext, registeredConfigurations)); + setRoutePlanner( + new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations)); + } + + @Override + public CloseableHttpClient build() { + final CloseableHttpClient httpClient = super.build(); + synchronized (trackedHttpClients) { + trackedHttpClients.add(httpClient); + } + return httpClient; + } + +} diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/services/CachingHttpClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/services/CachingHttpClientBuilderFactory.java new file mode 100644 index 0000000000..1eba4168bb --- /dev/null +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/services/CachingHttpClientBuilderFactory.java @@ -0,0 +1,35 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.services; + +import org.apache.http.impl.client.cache.CachingHttpClientBuilder; + +public interface CachingHttpClientBuilderFactory { + + CachingHttpClientBuilder newBuilder(); + +} From d2b106f8a0fd4606974ffe77037f802037e0c916 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 13 Aug 2016 15:28:07 +0000 Subject: [PATCH 079/204] HTTPCLIENT-1760: added protected methods to enumerate leased and available connections to PoolingHttpClientConnectionManager git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1756277 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/impl/conn/CPool.java | 11 +++++++++++ .../impl/conn/PoolingHttpClientConnectionManager.java | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java b/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java index 00238e9d93..f9cc0d6a62 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java @@ -36,6 +36,7 @@ import org.apache.http.conn.routing.HttpRoute; import org.apache.http.pool.AbstractConnPool; import org.apache.http.pool.ConnFactory; +import org.apache.http.pool.PoolEntryCallback; /** * @since 4.3 @@ -69,4 +70,14 @@ protected boolean validate(final CPoolEntry entry) { return !entry.getConnection().isStale(); } + @Override + protected void enumAvailable(final PoolEntryCallback callback) { + super.enumAvailable(callback); + } + + @Override + protected void enumLeased(final PoolEntryCallback callback) { + super.enumLeased(callback); + } + } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java index e5ee721e7a..0389a43d93 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java @@ -62,6 +62,7 @@ import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.pool.ConnFactory; import org.apache.http.pool.ConnPoolControl; +import org.apache.http.pool.PoolEntryCallback; import org.apache.http.pool.PoolStats; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; @@ -413,6 +414,14 @@ public void closeExpiredConnections() { this.pool.closeExpired(); } + protected void enumAvailable(final PoolEntryCallback callback) { + this.pool.enumAvailable(callback); + } + + protected void enumLeased(final PoolEntryCallback callback) { + this.pool.enumLeased(callback); + } + @Override public int getMaxTotal() { return this.pool.getMaxTotal(); From f638eec16b819ad0e2e4f992a97594986d45b33c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 13 Aug 2016 15:40:07 +0000 Subject: [PATCH 080/204] All services registered in the OSGi service registry provide the whole bundle header dictionary as vendor property value. Contributed by Christoph Fiehe git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1756279 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/osgi/impl/HttpProxyConfigurationActivator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index 4216976b41..b96c8acafc 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -86,14 +86,14 @@ public void start(final BundleContext context) throws Exception { // ensure we receive configurations for the proxy selector final Hashtable props = new Hashtable(); props.put(Constants.SERVICE_PID, getName()); - props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR)); + props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, PROXY_SERVICE_FACTORY_NAME); configurator = context.registerService(ManagedServiceFactory.class.getName(), this, props); props.clear(); props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID); - props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR)); + props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, BUILDER_FACTORY_SERVICE_NAME); clientFactory = context.registerService(HttpClientBuilderFactory.class.getName(), new OSGiClientBuilderFactory(context, registeredConfigurations, trackedHttpClients), @@ -101,7 +101,7 @@ public void start(final BundleContext context) throws Exception { props.clear(); props.put(Constants.SERVICE_PID, CACHEABLE_BUILDER_FACTORY_SERVICE_PID); - props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR)); + props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, CACHEABLE_BUILDER_FACTORY_SERVICE_NAME); clientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(), new OSGiCachingClientBuilderFactory(context, registeredConfigurations, trackedHttpClients), From 7870698373f275356cdcc1981851c41be60e08ef Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 28 Aug 2016 12:47:29 +0000 Subject: [PATCH 081/204] Typo in comment Contributed by Robin Stevens git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1758105 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/client/SystemDefaultCredentialsProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index debe142fa7..8a160d914d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -145,7 +145,7 @@ public Credentials getCredentials(final AuthScope authscope) { null, domain); } else { if (AuthSchemes.NTLM.equalsIgnoreCase(authscope.getScheme())) { - // Domian may be specified in a fully qualified user name + // Domain may be specified in a fully qualified user name return new NTCredentials( systemcreds.getUserName(), new String(systemcreds.getPassword()), From 8b5642ae925aed532e29aba6c2127e0bcf43f05f Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 28 Aug 2016 13:03:02 +0000 Subject: [PATCH 082/204] Support changing system default ProxySelector Contributed by Robin Stevens The `ProxySelectorRoutePlanner` class which got deprecated in favor of the `SystemDefaultRoutePlanner` could deal with: - `null` as default `ProxySelector` - a change in the default `ProxySelector` This change ports that behavior to the `SystemDefaultRoutePlanner`. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1758107 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/conn/SystemDefaultRoutePlanner.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java b/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java index 6b872b9eb4..30de52c193 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java @@ -54,13 +54,19 @@ public class SystemDefaultRoutePlanner extends DefaultRoutePlanner { private final ProxySelector proxySelector; + /** + * @param proxySelector the proxy selector, or {@code null} for the system default + */ public SystemDefaultRoutePlanner( final SchemePortResolver schemePortResolver, final ProxySelector proxySelector) { super(schemePortResolver); - this.proxySelector = proxySelector != null ? proxySelector : ProxySelector.getDefault(); + this.proxySelector = proxySelector; } + /** + * @param proxySelector the proxy selector, or {@code null} for the system default + */ public SystemDefaultRoutePlanner(final ProxySelector proxySelector) { this(null, proxySelector); } @@ -76,7 +82,15 @@ protected HttpHost determineProxy( } catch (final URISyntaxException ex) { throw new HttpException("Cannot convert host to URI: " + target, ex); } - final List proxies = this.proxySelector.select(targetURI); + ProxySelector proxySelectorInstance = this.proxySelector; + if (proxySelectorInstance == null) { + proxySelectorInstance = ProxySelector.getDefault(); + } + if (proxySelectorInstance == null) { + //The proxy selector can be "unset", so we must be able to deal with a null selector + return null; + } + final List proxies = proxySelectorInstance.select(targetURI); final Proxy p = chooseProxy(proxies); HttpHost result = null; if (p.type() == Proxy.Type.HTTP) { From 49fee5cf4e31f990a5d97b7f0d0d707a2208cd4c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 13 Sep 2016 18:33:02 +0000 Subject: [PATCH 083/204] HTTPCLIENT-1767: Null pointer dereference in EofSensorInputStream and ResponseEntityProxy EofSensorInputStream is generating NullPointerExceptions in some rare situations. This commit fixes that behaviour for the check methods by dereferencing the instance variable to a final local variable to ensure that if it is not null at the null guard, that it will be not null after that point also to successfully close/abort the stream In some rare cases, null parameters are sent to ReponseEntityProxy methods, this adds checks on those to ensure that the connections are still released, but the null variable is not dereferenced. Contributed by Peter Ansell git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1760586 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/conn/EofSensorInputStream.java | 21 +++++++++++-------- .../impl/execchain/ResponseEntityProxy.java | 12 ++++++++--- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java b/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java index 3b81bd0a47..50486311f1 100644 --- a/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java +++ b/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java @@ -193,14 +193,15 @@ public void close() throws IOException { */ protected void checkEOF(final int eof) throws IOException { - if ((wrappedStream != null) && (eof < 0)) { + final InputStream toCheckStream = wrappedStream; + if ((toCheckStream != null) && (eof < 0)) { try { boolean scws = true; // should close wrapped stream? if (eofWatcher != null) { - scws = eofWatcher.eofDetected(wrappedStream); + scws = eofWatcher.eofDetected(toCheckStream); } if (scws) { - wrappedStream.close(); + toCheckStream.close(); } } finally { wrappedStream = null; @@ -221,14 +222,15 @@ protected void checkEOF(final int eof) throws IOException { */ protected void checkClose() throws IOException { - if (wrappedStream != null) { + final InputStream toCloseStream = wrappedStream; + if (toCloseStream != null) { try { boolean scws = true; // should close wrapped stream? if (eofWatcher != null) { - scws = eofWatcher.streamClosed(wrappedStream); + scws = eofWatcher.streamClosed(toCloseStream); } if (scws) { - wrappedStream.close(); + toCloseStream.close(); } } finally { wrappedStream = null; @@ -251,14 +253,15 @@ protected void checkClose() throws IOException { */ protected void checkAbort() throws IOException { - if (wrappedStream != null) { + final InputStream toAbortStream = wrappedStream; + if (toAbortStream != null) { try { boolean scws = true; // should close wrapped stream? if (eofWatcher != null) { - scws = eofWatcher.streamAbort(wrappedStream); + scws = eofWatcher.streamAbort(toAbortStream); } if (scws) { - wrappedStream.close(); + toAbortStream.close(); } } finally { wrappedStream = null; diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java index 5955cbede3..ba2716326e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java @@ -98,7 +98,9 @@ public void consumeContent() throws IOException { @Override public void writeTo(final OutputStream outstream) throws IOException { try { - this.wrappedEntity.writeTo(outstream); + if (outstream != null) { + this.wrappedEntity.writeTo(outstream); + } releaseConnection(); } catch (final IOException ex) { abortConnection(); @@ -116,7 +118,9 @@ public boolean eofDetected(final InputStream wrapped) throws IOException { try { // there may be some cleanup required, such as // reading trailers after the response body: - wrapped.close(); + if (wrapped != null) { + wrapped.close(); + } releaseConnection(); } catch (final IOException ex) { abortConnection(); @@ -137,7 +141,9 @@ public boolean streamClosed(final InputStream wrapped) throws IOException { // this assumes that closing the stream will // consume the remainder of the response body: try { - wrapped.close(); + if (wrapped != null) { + wrapped.close(); + } releaseConnection(); } catch (final SocketException ex) { if (open) { From baf7e10e7896f8e7de748402aa3ffdd05d6e3359 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 24 Sep 2016 08:52:03 +0000 Subject: [PATCH 084/204] HTTPCLIENT-1770: OSGi metatype for org.apache.http.proxyconfigurator missing factoryPid Contributed by Julian Sedding git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1762113 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/resources/OSGI-INF/metatype/metatype.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml b/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml index ab59f1b36f..4879354c1a 100644 --- a/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml +++ b/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml @@ -69,7 +69,7 @@ - + From 07fe1b7cdb2ffd849261f2da383e03a5c791d760 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 24 Sep 2016 08:52:15 +0000 Subject: [PATCH 085/204] HTTPCLIENT-1771: improve OSGi webconsole display for org.apache.http.proxyconfigurator Contributed by Julian Sedding git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1762114 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/resources/OSGI-INF/metatype/metatype.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml b/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml index 4879354c1a..55d8879a16 100644 --- a/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml +++ b/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml @@ -67,6 +67,10 @@ name="%proxy.exceptions.name" description="%proxy.exceptions.description" /> + + From b99a5138cce39eff6c5c5374d9de90d24b03b9f2 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 30 Sep 2016 14:08:12 +0000 Subject: [PATCH 086/204] HTTPCLIENT-1772: [OSGi] WeakList needs to support "clear" method git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1762913 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/osgi/impl/WeakList.java | 5 +++++ .../java/org/apache/http/osgi/impl/WeakListTest.java | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java index 59ee6fd7fe..5325196cc7 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java @@ -62,6 +62,11 @@ public boolean add(final T t) { return innerList.add(new WeakReference(t)); } + @Override + public void clear() { + innerList.clear(); + } + private void checkReferences() { final ListIterator> references = innerList.listIterator(); while (references.hasNext()) { diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java index a930fa41bc..77770bf42d 100644 --- a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java @@ -59,4 +59,15 @@ public void testWeakList() { assertTrue(thrown); } + @Test + public void clearSupported() { + final WeakList list = new WeakList(); + + list.add("hello"); + assertEquals(1, list.size()); + + list.clear(); + assertEquals(0, list.size()); + } + } \ No newline at end of file From 85786663ea3f4561f2b9476a0c07ad3d97c335fe Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Fri, 30 Sep 2016 16:07:23 +0000 Subject: [PATCH 087/204] HTTPCLIENT-1773: [OSGi] HttpProxyConfigurationActivator does not unregister HttpClientBuilderFactory git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1762930 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/osgi/impl/HttpProxyConfigurationActivator.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index b96c8acafc..30e5dfdffb 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -66,6 +66,8 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M private ServiceRegistration clientFactory; + private ServiceRegistration cachingClientFactory; + private BundleContext context; private final Map registeredConfigurations = new LinkedHashMap(); @@ -103,7 +105,7 @@ public void start(final BundleContext context) throws Exception { props.put(Constants.SERVICE_PID, CACHEABLE_BUILDER_FACTORY_SERVICE_PID); props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, CACHEABLE_BUILDER_FACTORY_SERVICE_NAME); - clientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(), + cachingClientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(), new OSGiCachingClientBuilderFactory(context, registeredConfigurations, trackedHttpClients), props); } @@ -127,6 +129,10 @@ public void stop(final BundleContext context) throws Exception { clientFactory.unregister(); } + if (cachingClientFactory != null) { + cachingClientFactory.unregister(); + } + // ensure all http clients - generated with the - are terminated for (final CloseableHttpClient client : trackedHttpClients) { if (null != client) { From a388462654f157ca28064234ace1441ef04f24a2 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Tue, 4 Oct 2016 11:59:47 +0000 Subject: [PATCH 088/204] HTTPCLIENT-1777: [OSGi] remove duplication between OSGiClientBuilderFactory and OSGiCachingClientBuilderFactory git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1763267 13f79535-47bb-0310-9956-ffa450edef68 --- ...ava => HttpClientBuilderConfigurator.java} | 41 +++++-------- .../impl/HttpProxyConfigurationActivator.java | 9 ++- .../impl/OSGiCachingClientBuilderFactory.java | 35 ++++++----- .../impl/OSGiCachingHttpClientBuilder.java | 61 ------------------- .../osgi/impl/OSGiClientBuilderFactory.java | 28 ++++----- 5 files changed, 53 insertions(+), 121 deletions(-) rename httpclient-osgi/src/main/java/org/apache/http/osgi/impl/{OSGiHttpClientBuilder.java => HttpClientBuilderConfigurator.java} (62%) delete mode 100644 httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilder.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpClientBuilderConfigurator.java similarity index 62% rename from httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilder.java rename to httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpClientBuilderConfigurator.java index 69cdc3e38a..edd3d0035b 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilder.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpClientBuilderConfigurator.java @@ -26,40 +26,29 @@ */ package org.apache.http.osgi.impl; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; -/** - * @since 4.3 - */ -final class OSGiHttpClientBuilder extends HttpClientBuilder { +import java.util.Map; - private final Collection trackedHttpClients; +final class HttpClientBuilderConfigurator { - public OSGiHttpClientBuilder( + private final OSGiCredentialsProvider credentialsProvider; + + private final OSGiHttpRoutePlanner routePlanner; + + HttpClientBuilderConfigurator( final BundleContext bundleContext, - final Map registeredConfigurations, - final List trackedHttpClients) { - this.trackedHttpClients = trackedHttpClients; - setDefaultCredentialsProvider( - new OSGiCredentialsProvider(bundleContext, registeredConfigurations)); - setRoutePlanner( - new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations)); + final Map registeredConfigurations) { + credentialsProvider = new OSGiCredentialsProvider(bundleContext, registeredConfigurations); + routePlanner = new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations); } - @Override - public CloseableHttpClient build() { - final CloseableHttpClient httpClient = super.build(); - synchronized (trackedHttpClients) { - trackedHttpClients.add(httpClient); - } - return httpClient; + T configure(final T clientBuilder) { + clientBuilder + .setDefaultCredentialsProvider(credentialsProvider) + .setRoutePlanner(routePlanner); + return clientBuilder; } - } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index 30e5dfdffb..54470bd7bd 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -93,12 +93,15 @@ public void start(final BundleContext context) throws Exception { configurator = context.registerService(ManagedServiceFactory.class.getName(), this, props); + final HttpClientBuilderConfigurator configurator = + new HttpClientBuilderConfigurator(context, registeredConfigurations); + props.clear(); props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID); props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, BUILDER_FACTORY_SERVICE_NAME); clientFactory = context.registerService(HttpClientBuilderFactory.class.getName(), - new OSGiClientBuilderFactory(context, registeredConfigurations, trackedHttpClients), + new OSGiClientBuilderFactory(configurator, trackedHttpClients), props); props.clear(); @@ -106,8 +109,8 @@ public void start(final BundleContext context) throws Exception { props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, CACHEABLE_BUILDER_FACTORY_SERVICE_NAME); cachingClientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(), - new OSGiCachingClientBuilderFactory(context, registeredConfigurations, trackedHttpClients), - props); + new OSGiCachingClientBuilderFactory(configurator, trackedHttpClients), + props); } /** diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java index c496120847..19e0de6e1f 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java @@ -26,34 +26,37 @@ */ package org.apache.http.osgi.impl; +import java.util.List; + import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.cache.CachingHttpClientBuilder; import org.apache.http.osgi.services.CachingHttpClientBuilderFactory; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - -import java.util.List; -import java.util.Map; - -class OSGiCachingClientBuilderFactory implements CachingHttpClientBuilderFactory { - private final BundleContext bundleContext; +/** + * @since 4.3 + */ +final class OSGiCachingClientBuilderFactory implements CachingHttpClientBuilderFactory { - private final Map registeredConfigurations; + private final HttpClientBuilderConfigurator configurator; - private final List trackedHttpClients; + private List trackedHttpClients; - public OSGiCachingClientBuilderFactory( - final BundleContext bundleContext, - final Map registeredConfigurations, + OSGiCachingClientBuilderFactory( + final HttpClientBuilderConfigurator configurator, final List trackedHttpClients) { - this.bundleContext = bundleContext; - this.registeredConfigurations = registeredConfigurations; + this.configurator = configurator; this.trackedHttpClients = trackedHttpClients; } @Override public CachingHttpClientBuilder newBuilder() { - return new OSGiCachingHttpClientBuilder(bundleContext, registeredConfigurations, trackedHttpClients); + return configurator.configure(new CachingHttpClientBuilder() { + @Override + public CloseableHttpClient build() { + final CloseableHttpClient client = super.build(); + trackedHttpClients.add(client); + return client; + } + }); } } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java deleted file mode 100644 index 57adae5f2d..0000000000 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilder.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.osgi.impl; - -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.cache.CachingHttpClientBuilder; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - -import java.util.List; -import java.util.Map; - -final class OSGiCachingHttpClientBuilder extends CachingHttpClientBuilder { - - private final List trackedHttpClients; - - public OSGiCachingHttpClientBuilder( - final BundleContext bundleContext, - final Map registeredConfigurations, - final List trackedHttpClients) { - this.trackedHttpClients = trackedHttpClients; - setDefaultCredentialsProvider( - new OSGiCredentialsProvider(bundleContext, registeredConfigurations)); - setRoutePlanner( - new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations)); - } - - @Override - public CloseableHttpClient build() { - final CloseableHttpClient httpClient = super.build(); - synchronized (trackedHttpClients) { - trackedHttpClients.add(httpClient); - } - return httpClient; - } - -} diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java index a8d1ed5813..736da6ad8c 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java @@ -27,37 +27,35 @@ package org.apache.http.osgi.impl; import java.util.List; -import java.util.Map; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.osgi.services.HttpClientBuilderFactory; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - /** * @since 4.3 */ -public final class OSGiClientBuilderFactory implements HttpClientBuilderFactory { - - private final BundleContext bundleContext; +final class OSGiClientBuilderFactory implements HttpClientBuilderFactory { - private final Map registeredConfigurations; + private final HttpClientBuilderConfigurator configurator; private final List trackedHttpClients; - public OSGiClientBuilderFactory( - final BundleContext bundleContext, - final Map registeredConfigurations, + OSGiClientBuilderFactory( + final HttpClientBuilderConfigurator configurator, final List trackedHttpClients) { - this.bundleContext = bundleContext; - this.registeredConfigurations = registeredConfigurations; + this.configurator = configurator; this.trackedHttpClients = trackedHttpClients; } @Override public HttpClientBuilder newBuilder() { - return new OSGiHttpClientBuilder(bundleContext, registeredConfigurations, trackedHttpClients); + return configurator.configure(new HttpClientBuilder() { + @Override + public CloseableHttpClient build() { + final CloseableHttpClient client = super.build(); + trackedHttpClients.add(client); + return client; + } + }); } - } From 2838281a10d59700d37937cf9c39cac93bbce417 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Tue, 4 Oct 2016 12:00:00 +0000 Subject: [PATCH 089/204] HTTPCLIENT-1778: [OSGi] simplify handling of ManagedService based configurations - simplify ProxyConfiguration handling git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1763268 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/HttpClientBuilderConfigurator.java | 13 ++- .../impl/HttpProxyConfigurationActivator.java | 19 +++-- .../osgi/impl/OSGiCredentialsProvider.java | 31 +++---- .../http/osgi/impl/OSGiHttpRoutePlanner.java | 36 +++----- .../osgi/impl/TestOSGiHttpRoutePlanner.java | 83 +++++-------------- 5 files changed, 62 insertions(+), 120 deletions(-) diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpClientBuilderConfigurator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpClientBuilderConfigurator.java index edd3d0035b..2393c265d5 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpClientBuilderConfigurator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpClientBuilderConfigurator.java @@ -27,10 +27,9 @@ package org.apache.http.osgi.impl; import org.apache.http.impl.client.HttpClientBuilder; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; +import org.apache.http.osgi.services.ProxyConfiguration; -import java.util.Map; +import java.util.List; final class HttpClientBuilderConfigurator { @@ -38,11 +37,9 @@ final class HttpClientBuilderConfigurator { private final OSGiHttpRoutePlanner routePlanner; - HttpClientBuilderConfigurator( - final BundleContext bundleContext, - final Map registeredConfigurations) { - credentialsProvider = new OSGiCredentialsProvider(bundleContext, registeredConfigurations); - routePlanner = new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations); + HttpClientBuilderConfigurator(final List proxyConfigurations) { + credentialsProvider = new OSGiCredentialsProvider(proxyConfigurations); + routePlanner = new OSGiHttpRoutePlanner(proxyConfigurations); } T configure(final T clientBuilder) { diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index 54470bd7bd..f03bf4f1d6 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -33,6 +33,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.osgi.services.CachingHttpClientBuilderFactory; @@ -41,6 +42,7 @@ import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedServiceFactory; @@ -72,6 +74,8 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M private final Map registeredConfigurations = new LinkedHashMap(); + private final List proxyConfigurations = new CopyOnWriteArrayList(); + private final List trackedHttpClients; public HttpProxyConfigurationActivator() { @@ -93,8 +97,7 @@ public void start(final BundleContext context) throws Exception { configurator = context.registerService(ManagedServiceFactory.class.getName(), this, props); - final HttpClientBuilderConfigurator configurator = - new HttpClientBuilderConfigurator(context, registeredConfigurations); + final HttpClientBuilderConfigurator configurator = new HttpClientBuilderConfigurator(proxyConfigurations); props.clear(); props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID); @@ -171,6 +174,7 @@ public void updated(final String pid, @SuppressWarnings("rawtypes") final Dictio proxyConfiguration, config); registeredConfigurations.put(pid, configurationRegistration); + proxyConfigurations.add(proxyConfiguration); } else { proxyConfiguration = (OSGiProxyConfiguration) context.getService(registration.getReference()); } @@ -186,10 +190,13 @@ public void updated(final String pid, @SuppressWarnings("rawtypes") final Dictio */ @Override public void deleted(final String pid) { - final ServiceRegistration registeredConfiguration = registeredConfigurations.get(pid); - if (null != registeredConfiguration) { - registeredConfiguration.unregister(); - registeredConfigurations.remove(pid); + final ServiceRegistration registration = registeredConfigurations.remove(pid); + if (registration != null) { + final ServiceReference ref = registration.getReference(); + final ProxyConfiguration config = (ProxyConfiguration) context.getService(ref); + proxyConfigurations.remove(config); + context.ungetService(ref); + registration.unregister(); } } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java index e9d6e51471..2f6631bea3 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java @@ -26,30 +26,23 @@ */ package org.apache.http.osgi.impl; -import java.util.Map; +import java.util.List; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.osgi.services.ProxyConfiguration; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; /** * @since 4.3 */ final class OSGiCredentialsProvider implements CredentialsProvider { - private final BundleContext bundleContext; + private List proxyConfigurations; - private final Map registeredConfigurations; - - public OSGiCredentialsProvider( - final BundleContext bundleContext, - final Map registeredConfigurations) { - this.bundleContext = bundleContext; - this.registeredConfigurations = registeredConfigurations; + public OSGiCredentialsProvider(final List proxyConfigurations) { + this.proxyConfigurations = proxyConfigurations; } /** @@ -66,15 +59,13 @@ public void setCredentials(final AuthScope authscope, final Credentials credenti @Override public Credentials getCredentials(final AuthScope authscope) { // iterate over all active proxy configurations at the moment of getting the credential - for (final ServiceRegistration registration : registeredConfigurations.values()) { - final Object proxyConfigurationObject = bundleContext.getService(registration.getReference()); - if (proxyConfigurationObject != null) { - final ProxyConfiguration proxyConfiguration = (ProxyConfiguration) proxyConfigurationObject; - if (proxyConfiguration.isEnabled()) { - final AuthScope actual = new AuthScope(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); - if (authscope.match(actual) >= 12) { - return new UsernamePasswordCredentials(proxyConfiguration.getUsername(), proxyConfiguration.getPassword()); - } + for (final ProxyConfiguration proxyConfiguration : proxyConfigurations) { + if (proxyConfiguration.isEnabled()) { + final AuthScope actual = new AuthScope(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); + if (authscope.match(actual) >= 12) { + final String username = proxyConfiguration.getUsername(); + final String password = proxyConfiguration.getPassword(); + return new UsernamePasswordCredentials(username, password != null ? password : null); } } } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java index c422e39f48..2af252fbcc 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java @@ -26,8 +26,8 @@ */ package org.apache.http.osgi.impl; +import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -37,8 +37,6 @@ import org.apache.http.impl.conn.DefaultRoutePlanner; import org.apache.http.osgi.services.ProxyConfiguration; import org.apache.http.protocol.HttpContext; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; /** * @since 4.3 @@ -55,16 +53,11 @@ final class OSGiHttpRoutePlanner extends DefaultRoutePlanner { "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"); - private final BundleContext bundleContext; + private List proxyConfigurations; - private final Map registeredConfigurations; - - public OSGiHttpRoutePlanner( - final BundleContext bundleContext, - final Map registeredConfigurations) { + public OSGiHttpRoutePlanner(final List proxyConfigurations) { super(null); - this.bundleContext = bundleContext; - this.registeredConfigurations = registeredConfigurations; + this.proxyConfigurations = proxyConfigurations; } /** @@ -72,22 +65,17 @@ public OSGiHttpRoutePlanner( */ @Override protected HttpHost determineProxy(final HttpHost target, final HttpRequest request, final HttpContext context) throws HttpException { - ProxyConfiguration proxyConfiguration = null; HttpHost proxyHost = null; - for (final ServiceRegistration registration : registeredConfigurations.values()) { - final Object proxyConfigurationObject = bundleContext.getService(registration.getReference()); - if (proxyConfigurationObject != null) { - proxyConfiguration = (ProxyConfiguration) proxyConfigurationObject; - if (proxyConfiguration.isEnabled()) { - for (final String exception : proxyConfiguration.getProxyExceptions()) { - if (createMatcher(exception).matches(target.getHostName())) { - return null; - } - } - if (null == proxyHost) { - proxyHost = new HttpHost(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); + for (final ProxyConfiguration proxyConfiguration : proxyConfigurations) { + if (proxyConfiguration.isEnabled()) { + for (final String exception : proxyConfiguration.getProxyExceptions()) { + if (createMatcher(exception).matches(target.getHostName())) { + return null; } } + if (null == proxyHost) { + proxyHost = new HttpHost(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); + } } } diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java index 0b7bc29799..abc1014c75 100644 --- a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/TestOSGiHttpRoutePlanner.java @@ -26,22 +26,18 @@ */ package org.apache.http.osgi.impl; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import java.net.InetAddress; -import java.util.Map; -import java.util.TreeMap; +import java.util.Hashtable; import org.apache.http.HttpHost; import org.apache.http.osgi.services.ProxyConfiguration; import org.junit.Test; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.ServiceRegistration; /** @@ -50,48 +46,12 @@ public class TestOSGiHttpRoutePlanner { - final ProxyConfiguration pc1 = new ProxyConfiguration() { - @Override - public boolean isEnabled() {return true; } - @Override - public String getHostname() {return "proxy1"; } - @Override - public int getPort() { return 8080; } - @Override - public String getUsername() { return ""; } - @Override - public String getPassword() {return ""; } - @Override - public String[] getProxyExceptions() { return new String[]{"localhost", "127.0.0.1", ".apache.org"}; } - }; - - final ProxyConfiguration pc2 = new ProxyConfiguration() { - @Override - public boolean isEnabled() {return true; } - @Override - public String getHostname() {return "proxy2"; } - @Override - public int getPort() { return 9090; } - @Override - public String getUsername() { return ""; } - @Override - public String getPassword() {return ""; } - @Override - public String[] getProxyExceptions() { return new String[]{"localhost", "127.0.0.1", ".oracle.com", "12.34.34.8"}; } - }; + private final ProxyConfiguration pc1 = proxy("proxy1", 8080, "localhost", "127.0.0.1", ".apache.org"); + private final ProxyConfiguration pc2 = proxy("proxy2", 9090, "localhost", "127.0.0.1", ".oracle.com", "12.34.34.8"); @Test public void testDeterminProxy() throws Exception { - final ServiceReference sRef1 = mock(ServiceReference.class); - final ServiceRegistration sReg1 = mock(ServiceRegistration.class); - when(sReg1.getReference()).thenReturn(sRef1); - final BundleContext bc = mock(BundleContext.class); - when(bc.getService(sRef1)).thenReturn(this.pc1); - - final Map registrations = new TreeMap(); // TreeMap for order - registrations.put("foo1", sReg1); - - OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations); + OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(singletonList(pc1)); HttpHost proxy = planner.determineProxy(new HttpHost("localhost", 8090), null, null); assertNull(proxy); @@ -113,13 +73,7 @@ public void testDeterminProxy() throws Exception { // test with more than one registration of proxyConfiguration - final ServiceReference sRef2 = mock(ServiceReference.class); - final ServiceRegistration sReg2 = mock(ServiceRegistration.class); - when(sReg2.getReference()).thenReturn(sRef2); - when(bc.getService(sRef2)).thenReturn(this.pc2); - registrations.put("foo2", sReg2); - - planner = new OSGiHttpRoutePlanner(bc, registrations); + planner = new OSGiHttpRoutePlanner(asList(pc1, pc2)); proxy = planner.determineProxy(new HttpHost("localhost", 8090), null, null); assertNull(proxy); @@ -139,15 +93,7 @@ public void testDeterminProxy() throws Exception { @Test public void testMasking() throws Exception { - final ServiceReference sRef2 = mock(ServiceReference.class); - final ServiceRegistration sReg2 = mock(ServiceRegistration.class); - when(sReg2.getReference()).thenReturn(sRef2); - final BundleContext bc = mock(BundleContext.class); - when(bc.getService(sRef2)).thenReturn(this.pc2); - final Map registrations = new TreeMap(); - registrations.put("foo2", sReg2); - - final OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations); + final OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(singletonList(pc2)); HttpHost proxy = planner.determineProxy(new HttpHost("12.34.34.2", 4554), null, null); assertNotNull(proxy); @@ -157,4 +103,17 @@ public void testMasking() throws Exception { assertNotNull(proxy); } + private ProxyConfiguration proxy(final String host, final int port, final String... exceptions) { + final OSGiProxyConfiguration proxyConfiguration = new OSGiProxyConfiguration(); + final Hashtable config = new Hashtable(); + config.put("proxy.enabled", true); + config.put("proxy.host", host); + config.put("proxy.port", port); + config.put("proxy.user", ""); + config.put("proxy.password", ""); + config.put("proxy.exceptions", exceptions); + proxyConfiguration.update(config); + return proxyConfiguration; + } + } From 1c004a4870fbb4768585c3aeaa416826106a322b Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Tue, 4 Oct 2016 14:01:06 +0000 Subject: [PATCH 090/204] HTTPCLIENT-1779: [OSGi] support NTLM proxy authentication git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1763279 13f79535-47bb-0310-9956-ffa450edef68 --- .../osgi/impl/OSGiCredentialsProvider.java | 53 +++++++-- .../impl/OSGiCredentialsProviderTest.java | 101 ++++++++++++++++++ 2 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java index 2f6631bea3..7643c4347e 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCredentialsProvider.java @@ -28,8 +28,11 @@ import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; +import org.apache.http.auth.NTCredentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.osgi.services.ProxyConfiguration; @@ -39,9 +42,17 @@ */ final class OSGiCredentialsProvider implements CredentialsProvider { - private List proxyConfigurations; + private static final Log log = LogFactory.getLog(OSGiCredentialsProvider.class); - public OSGiCredentialsProvider(final List proxyConfigurations) { + private static final int HOST_AND_PORT_MATCH = 12; + + private static final String BASIC_SCHEME_NAME = "BASIC"; + + private static final String NTLM_SCHEME_NAME = "NTLM"; + + private final List proxyConfigurations; + + OSGiCredentialsProvider(final List proxyConfigurations) { this.proxyConfigurations = proxyConfigurations; } @@ -57,15 +68,17 @@ public void setCredentials(final AuthScope authscope, final Credentials credenti * {@inheritDoc} */ @Override - public Credentials getCredentials(final AuthScope authscope) { + public Credentials getCredentials(final AuthScope authScope) { // iterate over all active proxy configurations at the moment of getting the credential - for (final ProxyConfiguration proxyConfiguration : proxyConfigurations) { - if (proxyConfiguration.isEnabled()) { - final AuthScope actual = new AuthScope(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); - if (authscope.match(actual) >= 12) { - final String username = proxyConfiguration.getUsername(); - final String password = proxyConfiguration.getPassword(); - return new UsernamePasswordCredentials(username, password != null ? password : null); + for (final ProxyConfiguration config : proxyConfigurations) { + if (config.isEnabled() && isSuitable(config, authScope)) { + final String scheme = authScope.getScheme(); + if (BASIC_SCHEME_NAME.equals(scheme)) { + return new UsernamePasswordCredentials(config.getUsername(), config.getPassword()); + } else if (NTLM_SCHEME_NAME.equals(scheme)) { + return createNTCredentials(config); + } else { + log.debug("credentials requested for unsupported authentication scheme " + scheme); } } } @@ -81,4 +94,24 @@ public void clear() { // do nothing, not used in this version } + // suitable configurations match at least the host and port of the AuthScope + private boolean isSuitable(final ProxyConfiguration config, final AuthScope authScope) { + return authScope.match(new AuthScope(config.getHostname(), config.getPort())) >= HOST_AND_PORT_MATCH; + } + + private static Credentials createNTCredentials(final ProxyConfiguration config) { + final String domainAndUsername = config.getUsername(); + final String username; + final String domain; + final int index = domainAndUsername.indexOf("\\"); + if (index > -1) { + username = domainAndUsername.substring(index + 1); + domain = domainAndUsername.substring(0, index); + } else { + username = domainAndUsername; + domain = null; + } + return new NTCredentials(username, config.getPassword(), null, domain); + } + } diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java new file mode 100644 index 0000000000..81703fbc22 --- /dev/null +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/OSGiCredentialsProviderTest.java @@ -0,0 +1,101 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.NTCredentials; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.osgi.services.ProxyConfiguration; +import org.junit.Test; + +import java.util.Hashtable; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertThat; + +public class OSGiCredentialsProviderTest { + + private static final String HOST = "proxy.example.org"; + + private static final int PORT = 8080; + + @Test + public void basicAuthentication() { + final CredentialsProvider provider = credentialsProvider(proxy("user", "secret")); + final Credentials credentials = provider.getCredentials(new AuthScope(HOST, PORT, null, "BASIC")); + assertThat(credentials, instanceOf(UsernamePasswordCredentials.class)); + assertCredentials((UsernamePasswordCredentials) credentials, "user", "secret"); + } + + @Test + public void ntlmAuthenticationWithoutDomain() { + final CredentialsProvider provider = credentialsProvider(proxy("user", "secret")); + final Credentials credentials = provider.getCredentials(new AuthScope(HOST, PORT, null, "NTLM")); + assertThat(credentials, instanceOf(NTCredentials.class)); + assertCredentials((NTCredentials) credentials, "user", "secret", null); + } + + @Test + public void ntlmAuthenticationWithDomain() { + final CredentialsProvider provider = credentialsProvider(proxy("DOMAIN\\user", "secret")); + final Credentials credentials = provider.getCredentials(new AuthScope(HOST, PORT, null, "NTLM")); + assertThat(credentials, instanceOf(NTCredentials.class)); + assertCredentials((NTCredentials) credentials, "user", "secret", "DOMAIN"); + } + + private CredentialsProvider credentialsProvider(final ProxyConfiguration... proxies) { + return new OSGiCredentialsProvider(asList(proxies)); + } + + private void assertCredentials(final UsernamePasswordCredentials credentials, final String user, final String password) { + assertThat("Username mismatch", credentials.getUserName(), equalTo(user)); + assertThat("Password mismatch", credentials.getPassword(), equalTo(password)); + } + + private void assertCredentials(final NTCredentials credentials, final String user, final String password, final String domain) { + assertThat("Username mismatch", credentials.getUserName(), equalTo(user)); + assertThat("Password mismatch", credentials.getPassword(), equalTo(password)); + assertThat("Domain mismatch", credentials.getDomain(), equalTo(domain)); + } + + private ProxyConfiguration proxy(final String username, final String password) { + final OSGiProxyConfiguration proxyConfiguration = new OSGiProxyConfiguration(); + final Hashtable config = new Hashtable(); + config.put("proxy.enabled", true); + config.put("proxy.host", HOST); + config.put("proxy.port", PORT); + config.put("proxy.user", username); + config.put("proxy.password", password); + config.put("proxy.exceptions", new String[0]); + proxyConfiguration.update(config); + return proxyConfiguration; + } +} From db671e6ef0c26b44e3174bc999db87b685b865a3 Mon Sep 17 00:00:00 2001 From: Julian Sedding Date: Tue, 4 Oct 2016 14:41:07 +0000 Subject: [PATCH 091/204] HTTPCLIENT-1782: [OSGi] List of tracked HTTPClients is mutable but not thread-safe git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1763284 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/HttpProxyConfigurationActivator.java | 50 +++++++++++-------- .../impl/OSGiCachingClientBuilderFactory.java | 10 ++-- .../osgi/impl/OSGiClientBuilderFactory.java | 11 ++-- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index f03bf4f1d6..ae2d8c7e80 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -76,11 +76,7 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M private final List proxyConfigurations = new CopyOnWriteArrayList(); - private final List trackedHttpClients; - - public HttpProxyConfigurationActivator() { - trackedHttpClients = new WeakList(); - } + private final HttpClientTracker httpClientTracker = new HttpClientTracker(); /** * {@inheritDoc} @@ -104,7 +100,7 @@ public void start(final BundleContext context) throws Exception { props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, BUILDER_FACTORY_SERVICE_NAME); clientFactory = context.registerService(HttpClientBuilderFactory.class.getName(), - new OSGiClientBuilderFactory(configurator, trackedHttpClients), + new OSGiClientBuilderFactory(configurator, httpClientTracker), props); props.clear(); @@ -112,7 +108,7 @@ public void start(final BundleContext context) throws Exception { props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, CACHEABLE_BUILDER_FACTORY_SERVICE_NAME); cachingClientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(), - new OSGiCachingClientBuilderFactory(configurator, trackedHttpClients), + new OSGiCachingClientBuilderFactory(configurator, httpClientTracker), props); } @@ -125,6 +121,8 @@ public void stop(final BundleContext context) throws Exception { for (final ServiceRegistration registeredConfiguration : registeredConfigurations.values()) { registeredConfiguration.unregister(); } + // remove all tracked services + registeredConfigurations.clear(); // unregister service factory if (configurator != null) { @@ -139,17 +137,8 @@ public void stop(final BundleContext context) throws Exception { cachingClientFactory.unregister(); } - // ensure all http clients - generated with the - are terminated - for (final CloseableHttpClient client : trackedHttpClients) { - if (null != client) { - closeQuietly(client); - } - } - - // remove all tracked services - registeredConfigurations.clear(); - // remove all tracked created clients - trackedHttpClients.clear(); + // ensure all http clients are closed + httpClientTracker.closeAll(); } /** @@ -201,11 +190,28 @@ public void deleted(final String pid) { } private static void closeQuietly(final Closeable closeable) { - try { - closeable.close(); - } catch (final IOException e) { - // do nothing + if (closeable != null) { + try { + closeable.close(); + } catch (final IOException e) { + // do nothing + } } } + static class HttpClientTracker { + + private final List trackedHttpClients = new WeakList(); + + synchronized void track(final CloseableHttpClient client) { + trackedHttpClients.add(client); + } + + synchronized void closeAll() { + for (final CloseableHttpClient client : trackedHttpClients) { + closeQuietly(client); + } + trackedHttpClients.clear(); + } + } } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java index 19e0de6e1f..80661c83c6 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java @@ -26,8 +26,6 @@ */ package org.apache.http.osgi.impl; -import java.util.List; - import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.cache.CachingHttpClientBuilder; import org.apache.http.osgi.services.CachingHttpClientBuilderFactory; @@ -39,13 +37,13 @@ final class OSGiCachingClientBuilderFactory implements CachingHttpClientBuilderF private final HttpClientBuilderConfigurator configurator; - private List trackedHttpClients; + private final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker; OSGiCachingClientBuilderFactory( final HttpClientBuilderConfigurator configurator, - final List trackedHttpClients) { + final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker) { this.configurator = configurator; - this.trackedHttpClients = trackedHttpClients; + this.httpClientTracker = httpClientTracker; } @Override @@ -54,7 +52,7 @@ public CachingHttpClientBuilder newBuilder() { @Override public CloseableHttpClient build() { final CloseableHttpClient client = super.build(); - trackedHttpClients.add(client); + httpClientTracker.track(client); return client; } }); diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java index 736da6ad8c..84a76f86ea 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java @@ -26,11 +26,10 @@ */ package org.apache.http.osgi.impl; -import java.util.List; - import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.osgi.services.HttpClientBuilderFactory; + /** * @since 4.3 */ @@ -38,13 +37,13 @@ final class OSGiClientBuilderFactory implements HttpClientBuilderFactory { private final HttpClientBuilderConfigurator configurator; - private final List trackedHttpClients; + private final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker; OSGiClientBuilderFactory( final HttpClientBuilderConfigurator configurator, - final List trackedHttpClients) { + final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker) { this.configurator = configurator; - this.trackedHttpClients = trackedHttpClients; + this.httpClientTracker = httpClientTracker; } @Override @@ -53,7 +52,7 @@ public HttpClientBuilder newBuilder() { @Override public CloseableHttpClient build() { final CloseableHttpClient client = super.build(); - trackedHttpClients.add(client); + httpClientTracker.track(client); return client; } }); From 0514407d8c5ee5a04a368ba70513c410bfc150f6 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 19 Nov 2016 16:40:54 +0000 Subject: [PATCH 092/204] Upgraded HttpCore to version 4.4.5 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1770506 13f79535-47bb-0310-9956-ffa450edef68 --- .../InternalEntityEnclosingHttpRequest.java | 2 - .../client/fluent/InternalHttpRequest.java | 2 - .../impl/client/cache/CachingHttpClient.java | 5 +- .../http/client/cache/HeaderConstants.java | 3 - .../http/client/cache/HttpCacheContext.java | 2 - .../http/client/cache/HttpCacheEntry.java | 5 +- .../apache/http/client/cache/InputLimit.java | 3 - .../client/cache/BasicHttpCacheStorage.java | 5 +- .../impl/client/cache/BasicIdGenerator.java | 8 +-- .../http/impl/client/cache/CacheEntity.java | 5 +- .../impl/client/cache/CacheEntryUpdater.java | 5 +- .../impl/client/cache/CacheInvalidator.java | 5 +- .../impl/client/cache/CacheKeyGenerator.java | 5 +- .../client/cache/CacheValidityPolicy.java | 5 +- .../client/cache/CacheableRequestPolicy.java | 5 +- .../cache/CachedHttpResponseGenerator.java | 5 +- .../CachedResponseSuitabilityChecker.java | 5 +- .../http/impl/client/cache/CachingExec.java | 5 +- .../impl/client/cache/CachingHttpClients.java | 2 - .../impl/client/cache/CombinedEntity.java | 2 - .../cache/ConditionalRequestBuilder.java | 5 +- .../client/cache/DefaultFailureCache.java | 7 ++- .../DefaultHttpCacheEntrySerializer.java | 5 +- .../ExponentialBackOffSchedulingStrategy.java | 9 +-- .../impl/client/cache/FailureCacheValue.java | 5 +- .../http/impl/client/cache/FileResource.java | 5 +- .../client/cache/FileResourceFactory.java | 5 +- .../http/impl/client/cache/HeapResource.java | 5 +- .../client/cache/HeapResourceFactory.java | 5 +- .../http/impl/client/cache/IOUtils.java | 2 - .../cache/ImmediateSchedulingStrategy.java | 9 +-- .../client/cache/ManagedHttpCacheStorage.java | 5 +- .../client/cache/OptionsHttp11Response.java | 5 +- .../http/impl/client/cache/Proxies.java | 2 - .../cache/RequestProtocolCompliance.java | 5 +- .../impl/client/cache/ResourceReference.java | 5 +- .../client/cache/ResponseCachingPolicy.java | 5 +- .../cache/ResponseProtocolCompliance.java | 5 +- .../client/cache/ResponseProxyHandler.java | 2 - .../cache/SizeLimitedResponseReader.java | 2 - .../auth/win/CurrentWindowsCredentials.java | 5 +- .../auth/win/WindowsCredentialsProvider.java | 5 +- .../auth/win/WindowsNTLMSchemeFactory.java | 5 +- .../impl/auth/win/WindowsNegotiateScheme.java | 2 - .../win/WindowsNegotiateSchemeFactory.java | 5 +- .../apache/http/auth/params/AuthParams.java | 5 +- .../apache/http/client/params/AuthPolicy.java | 3 - .../http/client/params/ClientParamBean.java | 2 - .../http/client/params/CookiePolicy.java | 3 - .../http/client/params/HttpClientParams.java | 2 - .../protocol/ClientContextConfigurer.java | 2 - .../protocol/RequestProxyAuthentication.java | 5 +- .../protocol/RequestTargetAuthentication.java | 5 +- .../client/protocol/ResponseAuthCache.java | 5 +- .../org/apache/http/client/utils/JdkIdn.java | 5 +- .../apache/http/client/utils/Punycode.java | 5 +- .../apache/http/client/utils/Rfc3492Idn.java | 5 +- .../http/conn/BasicEofSensorWatcher.java | 2 - .../apache/http/conn/BasicManagedEntity.java | 2 - .../conn/MultihomePlainSocketFactory.java | 5 +- .../conn/params/ConnManagerParamBean.java | 2 - .../http/conn/params/ConnManagerParams.java | 5 +- .../http/conn/params/ConnPerRouteBean.java | 5 +- .../http/conn/params/ConnRouteParamBean.java | 2 - .../http/conn/params/ConnRouteParams.java | 5 +- .../http/conn/scheme/PlainSocketFactory.java | 5 +- .../http/conn/ssl/SSLContextBuilder.java | 3 - .../org/apache/http/conn/ssl/SSLContexts.java | 5 +- .../http/conn/ssl/SSLSocketFactory.java | 5 +- .../cookie/params/CookieSpecParamBean.java | 2 - .../client/AbstractAuthenticationHandler.java | 5 +- .../http/impl/client/AbstractHttpClient.java | 61 +------------------ .../client/AuthenticationStrategyAdaptor.java | 5 +- .../http/impl/client/AutoRetryHttpClient.java | 5 +- .../http/impl/client/ClientParamsStack.java | 2 - .../client/CloseableHttpResponseProxy.java | 2 - .../client/ContentEncodingHttpClient.java | 5 +- .../http/impl/client/DefaultHttpClient.java | 5 +- .../DefaultProxyAuthenticationHandler.java | 5 +- .../impl/client/DefaultRedirectHandler.java | 5 +- .../DefaultRedirectStrategyAdaptor.java | 5 +- .../impl/client/DefaultRequestDirector.java | 2 - .../DefaultTargetAuthenticationHandler.java | 5 +- .../http/impl/client/RoutedRequest.java | 4 +- .../impl/client/SystemDefaultHttpClient.java | 5 +- .../impl/client/TunnelRefusedException.java | 2 - .../impl/conn/AbstractClientConnAdapter.java | 2 - .../conn/BasicClientConnectionManager.java | 9 +-- .../impl/conn/DefaultClientConnection.java | 4 +- .../conn/DefaultClientConnectionOperator.java | 7 ++- .../impl/conn/DefaultHttpRoutePlanner.java | 7 ++- .../http/impl/conn/DefaultResponseParser.java | 5 +- .../impl/conn/LoggingSessionInputBuffer.java | 5 +- .../impl/conn/LoggingSessionOutputBuffer.java | 5 +- .../conn/ManagedClientConnectionImpl.java | 2 - .../conn/PoolingClientConnectionManager.java | 5 +- .../impl/conn/ProxySelectorRoutePlanner.java | 4 +- .../http/impl/conn/SchemeRegistryFactory.java | 5 +- .../impl/conn/SingleClientConnManager.java | 10 +-- .../impl/conn/tsccm/AbstractConnPool.java | 5 -- .../impl/conn/tsccm/BasicPoolEntryRef.java | 2 +- .../tsccm/ThreadSafeClientConnManager.java | 11 ++-- .../http/impl/cookie/BestMatchSpec.java | 5 +- .../impl/cookie/BestMatchSpecFactory.java | 5 +- .../http/impl/cookie/BrowserCompatSpec.java | 5 +- .../impl/cookie/BrowserCompatSpecFactory.java | 5 +- .../BrowserCompatVersionAttributeHandler.java | 5 +- .../http/impl/cookie/DateParseException.java | 3 - .../apache/http/impl/cookie/DateUtils.java | 3 - .../http/impl/cookie/IgnoreSpecFactory.java | 5 +- .../impl/cookie/NetscapeDraftSpecFactory.java | 5 +- .../impl/cookie/PublicSuffixListParser.java | 5 +- .../http/impl/cookie/RFC2109SpecFactory.java | 5 +- .../http/impl/cookie/RFC2965SpecFactory.java | 5 +- .../main/java/org/apache/http/auth/AUTH.java | 3 - .../java/org/apache/http/auth/AuthOption.java | 5 +- .../apache/http/auth/AuthSchemeRegistry.java | 5 +- .../java/org/apache/http/auth/AuthScope.java | 5 +- .../java/org/apache/http/auth/AuthState.java | 2 - .../http/auth/AuthenticationException.java | 2 - .../apache/http/auth/BasicUserPrincipal.java | 5 +- .../auth/InvalidCredentialsException.java | 3 - .../apache/http/auth/KerberosCredentials.java | 5 +- .../auth/MalformedChallengeException.java | 2 - .../org/apache/http/auth/NTCredentials.java | 5 +- .../org/apache/http/auth/NTUserPrincipal.java | 5 +- .../auth/UsernamePasswordCredentials.java | 5 +- .../client/CircularRedirectException.java | 3 - .../http/client/ClientProtocolException.java | 3 - .../http/client/HttpResponseException.java | 3 - .../client/NonRepeatableRequestException.java | 2 - .../apache/http/client/RedirectException.java | 2 - .../http/client/config/AuthSchemes.java | 3 - .../http/client/config/CookieSpecs.java | 3 - .../http/client/config/RequestConfig.java | 5 +- .../http/client/entity/EntityBuilder.java | 2 - .../entity/LazyDecompressingInputStream.java | 3 - .../client/entity/UrlEncodedFormEntity.java | 2 - .../http/client/methods/HttpDelete.java | 3 - .../HttpEntityEnclosingRequestBase.java | 2 - .../apache/http/client/methods/HttpGet.java | 3 - .../apache/http/client/methods/HttpHead.java | 3 - .../http/client/methods/HttpOptions.java | 2 - .../apache/http/client/methods/HttpPatch.java | 3 - .../apache/http/client/methods/HttpPost.java | 3 - .../apache/http/client/methods/HttpPut.java | 3 - .../http/client/methods/HttpRequestBase.java | 2 - .../client/methods/HttpRequestWrapper.java | 2 - .../apache/http/client/methods/HttpTrace.java | 3 - .../http/client/methods/RequestBuilder.java | 2 - .../client/protocol/HttpClientContext.java | 2 - .../protocol/RequestAcceptEncoding.java | 5 +- .../client/protocol/RequestAddCookies.java | 5 +- .../client/protocol/RequestAuthCache.java | 5 +- .../protocol/RequestClientConnControl.java | 5 +- .../protocol/RequestDefaultHeaders.java | 5 +- .../protocol/RequestExpectContinue.java | 5 +- .../protocol/ResponseContentEncoding.java | 5 +- .../protocol/ResponseProcessCookies.java | 5 +- .../apache/http/client/utils/CloneUtils.java | 3 - .../apache/http/client/utils/DateUtils.java | 2 - .../apache/http/client/utils/URIBuilder.java | 2 - .../apache/http/client/utils/URIUtils.java | 2 - .../http/client/utils/URLEncodedUtils.java | 2 - .../http/conn/ConnectTimeoutException.java | 2 - .../conn/ConnectionPoolTimeoutException.java | 3 - .../http/conn/EofSensorInputStream.java | 2 - .../http/conn/HttpHostConnectException.java | 2 - .../http/conn/UnsupportedSchemeException.java | 3 - .../http/conn/routing/BasicRouteDirector.java | 5 +- .../apache/http/conn/routing/HttpRoute.java | 5 +- .../http/conn/routing/RouteTracker.java | 2 - .../org/apache/http/conn/scheme/Scheme.java | 5 +- .../http/conn/scheme/SchemeRegistry.java | 5 +- .../socket/PlainConnectionSocketFactory.java | 5 +- .../conn/ssl/AllowAllHostnameVerifier.java | 5 +- .../ssl/BrowserCompatHostnameVerifier.java | 5 +- .../conn/ssl/DefaultHostnameVerifier.java | 5 +- .../http/conn/ssl/NoopHostnameVerifier.java | 5 +- .../conn/ssl/SSLConnectionSocketFactory.java | 6 +- .../http/conn/ssl/StrictHostnameVerifier.java | 5 +- .../http/conn/util/InetAddressUtils.java | 3 - .../http/conn/util/PublicSuffixList.java | 5 +- .../conn/util/PublicSuffixListParser.java | 5 +- .../http/conn/util/PublicSuffixMatcher.java | 5 +- .../conn/util/PublicSuffixMatcherLoader.java | 5 +- .../http/cookie/CookieIdentityComparator.java | 5 +- .../org/apache/http/cookie/CookieOrigin.java | 5 +- .../http/cookie/CookiePathComparator.java | 5 +- .../http/cookie/CookiePriorityComparator.java | 5 +- .../CookieRestrictionViolationException.java | 3 - .../http/cookie/CookieSpecRegistry.java | 5 +- .../http/cookie/MalformedCookieException.java | 2 - .../apache/http/impl/auth/AuthSchemeBase.java | 2 - .../apache/http/impl/auth/BasicScheme.java | 2 - .../http/impl/auth/BasicSchemeFactory.java | 5 +- .../apache/http/impl/auth/DigestScheme.java | 2 - .../http/impl/auth/DigestSchemeFactory.java | 5 +- .../apache/http/impl/auth/GGSSchemeBase.java | 2 - .../apache/http/impl/auth/KerberosScheme.java | 2 - .../http/impl/auth/KerberosSchemeFactory.java | 5 +- .../http/impl/auth/NTLMEngineException.java | 2 - .../apache/http/impl/auth/NTLMEngineImpl.java | 2 - .../org/apache/http/impl/auth/NTLMScheme.java | 2 - .../http/impl/auth/NTLMSchemeFactory.java | 5 +- .../apache/http/impl/auth/RFC2617Scheme.java | 2 - .../apache/http/impl/auth/SPNegoScheme.java | 2 - .../http/impl/auth/SPNegoSchemeFactory.java | 5 +- .../UnsupportedDigestAlgorithmException.java | 3 - .../impl/client/AbstractResponseHandler.java | 5 +- .../client/AuthenticationStrategyImpl.java | 5 +- .../http/impl/client/BasicAuthCache.java | 5 +- .../http/impl/client/BasicCookieStore.java | 7 +-- .../impl/client/BasicCredentialsProvider.java | 5 +- .../impl/client/BasicResponseHandler.java | 5 +- .../http/impl/client/CloseableHttpClient.java | 5 +- .../DefaultConnectionKeepAliveStrategy.java | 5 +- .../DefaultHttpRequestRetryHandler.java | 5 +- .../impl/client/DefaultRedirectStrategy.java | 5 +- ...efaultServiceUnavailableRetryStrategy.java | 5 +- .../impl/client/DefaultUserTokenHandler.java | 5 +- .../client/EntityEnclosingRequestWrapper.java | 2 - .../client/FutureRequestExecutionService.java | 5 +- .../http/impl/client/HttpClientBuilder.java | 2 - .../apache/http/impl/client/HttpClients.java | 2 - .../http/impl/client/InternalHttpClient.java | 5 +- .../http/impl/client/LaxRedirectStrategy.java | 5 +- .../http/impl/client/MinimalHttpClient.java | 5 +- .../impl/client/NoopUserTokenHandler.java | 5 +- .../client/ProxyAuthenticationStrategy.java | 5 +- .../http/impl/client/RedirectLocations.java | 3 - .../http/impl/client/RequestWrapper.java | 2 - .../StandardHttpRequestRetryHandler.java | 5 +- .../SystemDefaultCredentialsProvider.java | 5 +- .../client/TargetAuthenticationStrategy.java | 5 +- .../BasicHttpClientConnectionManager.java | 23 ++----- .../java/org/apache/http/impl/conn/CPool.java | 5 +- .../org/apache/http/impl/conn/CPoolEntry.java | 5 +- .../org/apache/http/impl/conn/CPoolProxy.java | 2 - .../conn/ConnectionShutdownException.java | 3 - .../DefaultHttpClientConnectionOperator.java | 5 +- .../impl/conn/DefaultHttpResponseParser.java | 2 - .../DefaultHttpResponseParserFactory.java | 5 +- .../DefaultManagedHttpClientConnection.java | 2 - .../impl/conn/DefaultProxyRoutePlanner.java | 5 +- .../http/impl/conn/DefaultRoutePlanner.java | 5 +- .../impl/conn/DefaultSchemePortResolver.java | 5 +- .../http/impl/conn/LoggingInputStream.java | 3 - .../LoggingManagedHttpClientConnection.java | 16 +++-- .../http/impl/conn/LoggingOutputStream.java | 3 - .../ManagedHttpClientConnectionFactory.java | 5 +- .../PoolingHttpClientConnectionManager.java | 5 +- .../impl/conn/SystemDefaultRoutePlanner.java | 5 +- .../java/org/apache/http/impl/conn/Wire.java | 5 +- .../AbstractCookieAttributeHandler.java | 5 +- .../http/impl/cookie/AbstractCookieSpec.java | 5 +- .../http/impl/cookie/BasicClientCookie.java | 2 - .../http/impl/cookie/BasicClientCookie2.java | 2 - .../http/impl/cookie/BasicCommentHandler.java | 5 +- .../http/impl/cookie/BasicDomainHandler.java | 5 +- .../http/impl/cookie/BasicExpiresHandler.java | 5 +- .../http/impl/cookie/BasicMaxAgeHandler.java | 5 +- .../http/impl/cookie/BasicPathHandler.java | 5 +- .../http/impl/cookie/BasicSecureHandler.java | 5 +- .../http/impl/cookie/CookieSpecBase.java | 5 +- .../http/impl/cookie/DefaultCookieSpec.java | 5 +- .../cookie/DefaultCookieSpecProvider.java | 5 +- .../apache/http/impl/cookie/IgnoreSpec.java | 5 +- .../http/impl/cookie/IgnoreSpecProvider.java | 5 +- .../http/impl/cookie/LaxExpiresHandler.java | 5 +- .../http/impl/cookie/LaxMaxAgeHandler.java | 5 +- .../impl/cookie/NetscapeDomainHandler.java | 5 +- .../cookie/NetscapeDraftHeaderParser.java | 5 +- .../http/impl/cookie/NetscapeDraftSpec.java | 5 +- .../cookie/NetscapeDraftSpecProvider.java | 5 +- .../impl/cookie/PublicSuffixDomainFilter.java | 5 +- .../impl/cookie/RFC2109DomainHandler.java | 5 +- .../apache/http/impl/cookie/RFC2109Spec.java | 5 +- .../http/impl/cookie/RFC2109SpecProvider.java | 5 +- .../impl/cookie/RFC2109VersionHandler.java | 5 +- .../RFC2965CommentUrlAttributeHandler.java | 5 +- .../RFC2965DiscardAttributeHandler.java | 5 +- .../cookie/RFC2965DomainAttributeHandler.java | 5 +- .../cookie/RFC2965PortAttributeHandler.java | 5 +- .../apache/http/impl/cookie/RFC2965Spec.java | 5 +- .../http/impl/cookie/RFC2965SpecProvider.java | 5 +- .../RFC2965VersionAttributeHandler.java | 5 +- .../http/impl/cookie/RFC6265CookieSpec.java | 5 +- .../cookie/RFC6265CookieSpecProvider.java | 5 +- .../http/impl/cookie/RFC6265LaxSpec.java | 5 +- .../http/impl/cookie/RFC6265StrictSpec.java | 5 +- .../impl/execchain/BackoffStrategyExec.java | 5 +- .../http/impl/execchain/ConnectionHolder.java | 5 +- .../impl/execchain/HttpResponseProxy.java | 2 - .../http/impl/execchain/MainClientExec.java | 5 +- .../impl/execchain/MinimalClientExec.java | 5 +- .../http/impl/execchain/ProtocolExec.java | 5 +- .../http/impl/execchain/RedirectExec.java | 5 +- .../execchain/RequestAbortedException.java | 3 - .../impl/execchain/RequestEntityProxy.java | 2 - .../impl/execchain/ResponseEntityProxy.java | 2 - .../apache/http/impl/execchain/RetryExec.java | 5 +- .../ServiceUnavailableRetryExec.java | 5 +- .../execchain/TunnelRefusedException.java | 2 - pom.xml | 2 +- 305 files changed, 612 insertions(+), 751 deletions(-) diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalEntityEnclosingHttpRequest.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalEntityEnclosingHttpRequest.java index 6e0b4d64a4..a7972b8bf6 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalEntityEnclosingHttpRequest.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalEntityEnclosingHttpRequest.java @@ -32,10 +32,8 @@ import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.protocol.HTTP; -@NotThreadSafe class InternalEntityEnclosingHttpRequest extends InternalHttpRequest implements HttpEntityEnclosingRequest { private HttpEntity entity; diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java index 8d45954246..0dccb31ab8 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java @@ -34,7 +34,6 @@ import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.Configurable; import org.apache.http.client.methods.HttpExecutionAware; @@ -44,7 +43,6 @@ import org.apache.http.message.BasicRequestLine; import org.apache.http.util.Args; -@NotThreadSafe class InternalHttpRequest extends AbstractHttpMessage implements HttpUriRequest, HttpExecutionAware, Configurable { diff --git a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java index a54ff19668..0443ce61c1 100644 --- a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java +++ b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java @@ -57,7 +57,8 @@ import org.apache.http.ProtocolException; import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; @@ -126,7 +127,7 @@ * @deprecated (4.3) use {@link CachingHttpClientBuilder} or {@link CachingHttpClients}. */ @Deprecated -@ThreadSafe // So long as the responseCache implementation is threadsafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class CachingHttpClient implements HttpClient { /** diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/HeaderConstants.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/HeaderConstants.java index 0a25f24b7a..37213826e0 100644 --- a/httpclient-cache/src/main/java/org/apache/http/client/cache/HeaderConstants.java +++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HeaderConstants.java @@ -26,13 +26,10 @@ */ package org.apache.http.client.cache; -import org.apache.http.annotation.Immutable; - /** * Records static constants for various HTTP header names. * @since 4.1 */ -@Immutable public class HeaderConstants { public static final String GET_METHOD = "GET"; diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheContext.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheContext.java index 6c8af1dd63..f1a0d19280 100644 --- a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheContext.java +++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheContext.java @@ -26,7 +26,6 @@ */ package org.apache.http.client.cache; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; @@ -34,7 +33,6 @@ /** * @since 4.3 */ -@NotThreadSafe public class HttpCacheContext extends HttpClientContext { /** diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java index d8bf81b517..c537a48e04 100644 --- a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java +++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java @@ -36,7 +36,8 @@ import org.apache.http.HeaderIterator; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.utils.DateUtils; import org.apache.http.message.HeaderGroup; import org.apache.http.protocol.HTTP; @@ -51,7 +52,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class HttpCacheEntry implements Serializable { private static final long serialVersionUID = -6300496422359477413L; diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/InputLimit.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/InputLimit.java index dd96eebc3f..4d2ff43795 100644 --- a/httpclient-cache/src/main/java/org/apache/http/client/cache/InputLimit.java +++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/InputLimit.java @@ -26,15 +26,12 @@ */ package org.apache.http.client.cache; -import org.apache.http.annotation.NotThreadSafe; - /** * Used to limiting the size of an incoming response body of * unknown size that is optimistically being read in anticipation * of caching it. * @since 4.1 */ -@NotThreadSafe // reached public class InputLimit { private final long value; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheStorage.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheStorage.java index 76a525c42d..56d8a2085c 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheStorage.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheStorage.java @@ -28,7 +28,8 @@ import java.io.IOException; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.HttpCacheStorage; import org.apache.http.client.cache.HttpCacheUpdateCallback; @@ -43,7 +44,7 @@ * * @since 4.1 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class BasicHttpCacheStorage implements HttpCacheStorage { private final CacheMap entries; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicIdGenerator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicIdGenerator.java index 04236abdcc..5cdf45b896 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicIdGenerator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicIdGenerator.java @@ -33,19 +33,17 @@ import java.util.Formatter; import java.util.Locale; -import org.apache.http.annotation.GuardedBy; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * Should produce reasonably unique tokens. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) class BasicIdGenerator { private final String hostname; private final SecureRandom rnd; - - @GuardedBy("this") private long count; public BasicIdGenerator() { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java index 66e4af749a..529d6983aa 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java @@ -33,12 +33,13 @@ import org.apache.http.Header; import org.apache.http.HttpEntity; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.protocol.HTTP; import org.apache.http.util.Args; -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class CacheEntity implements HttpEntity, Serializable { private static final long serialVersionUID = -3467082284120936233L; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java index 4801b9dcbc..aa4c83cf43 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java @@ -36,7 +36,8 @@ import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.Resource; @@ -52,7 +53,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) class CacheEntryUpdater { private final ResourceFactory resourceFactory; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java index 57c2d913b1..84cc5ef0d4 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java @@ -37,7 +37,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.HttpCacheInvalidator; @@ -51,7 +52,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) class CacheInvalidator implements HttpCacheInvalidator { private final HttpCacheStorage storage; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java index 3d006d5fb9..91ca500eb7 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java @@ -40,7 +40,8 @@ import org.apache.http.HeaderElement; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.utils.URIUtils; @@ -48,7 +49,7 @@ /** * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class CacheKeyGenerator { private static final URI BASE_URI = URI.create("http://example.com/"); diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java index 7690e8aff9..2231fc6c7c 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java @@ -31,7 +31,8 @@ import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.utils.DateUtils; @@ -40,7 +41,7 @@ /** * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class CacheValidityPolicy { public static final long MAX_AGE = 2147483648L; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java index d7877034e2..356bd2ec83 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java @@ -33,7 +33,8 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; /** @@ -41,7 +42,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class CacheableRequestPolicy { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java index f74a2e42c4..42c01e9af3 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java @@ -33,7 +33,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.methods.CloseableHttpResponse; @@ -48,7 +49,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) class CachedHttpResponseGenerator { private final CacheValidityPolicy validityStrategy; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java index e7c940c6e2..8f53971574 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java @@ -35,7 +35,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpStatus; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.utils.DateUtils; @@ -46,7 +47,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) class CachedResponseSuitabilityChecker { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java index d9c63dd9a5..67f5748523 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java @@ -49,7 +49,8 @@ import org.apache.http.ProtocolException; import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.CacheResponseStatus; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheContext; @@ -99,7 +100,7 @@ * * @since 4.3 */ -@ThreadSafe // So long as the responseCache implementation is threadsafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class CachingExec implements ClientExecChain { private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClients.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClients.java index 35beb6ddee..36c034bc35 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClients.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClients.java @@ -29,7 +29,6 @@ import java.io.File; -import org.apache.http.annotation.Immutable; import org.apache.http.impl.client.CloseableHttpClient; /** @@ -38,7 +37,6 @@ * * @since 4.3 */ -@Immutable public class CachingHttpClients { private CachingHttpClients() { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java index a4cd65ce3c..c665339a12 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java @@ -32,12 +32,10 @@ import java.io.OutputStream; import java.io.SequenceInputStream; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.cache.Resource; import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.util.Args; -@NotThreadSafe class CombinedEntity extends AbstractHttpEntity { private final Resource resource; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java index 0f4bd09627..9caa048e0b 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java @@ -31,7 +31,8 @@ import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.methods.HttpRequestWrapper; @@ -39,7 +40,7 @@ /** * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class ConditionalRequestBuilder { /** diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultFailureCache.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultFailureCache.java index c0626faa01..8000b9ce6b 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultFailureCache.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultFailureCache.java @@ -26,19 +26,20 @@ */ package org.apache.http.impl.client.cache; -import org.apache.http.annotation.ThreadSafe; - import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; + /** * Implements a bounded failure cache. The oldest entries are discarded when * the maximum size is exceeded. * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class DefaultFailureCache implements FailureCache { static final int DEFAULT_MAX_SIZE = 1000; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultHttpCacheEntrySerializer.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultHttpCacheEntrySerializer.java index f84501bcbc..9572b784b3 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultHttpCacheEntrySerializer.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/DefaultHttpCacheEntrySerializer.java @@ -32,7 +32,8 @@ import java.io.ObjectOutputStream; import java.io.OutputStream; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.HttpCacheEntrySerializationException; import org.apache.http.client.cache.HttpCacheEntrySerializer; @@ -45,7 +46,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultHttpCacheEntrySerializer implements HttpCacheEntrySerializer { @Override diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ExponentialBackOffSchedulingStrategy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ExponentialBackOffSchedulingStrategy.java index 21b644ff8b..66aa5325ad 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ExponentialBackOffSchedulingStrategy.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ExponentialBackOffSchedulingStrategy.java @@ -26,13 +26,14 @@ */ package org.apache.http.impl.client.cache; -import org.apache.http.annotation.ThreadSafe; -import org.apache.http.util.Args; - import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; +import org.apache.http.util.Args; + /** * An implementation that backs off exponentially based on the number of * consecutive failed attempts stored in the @@ -56,7 +57,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class ExponentialBackOffSchedulingStrategy implements SchedulingStrategy { public static final long DEFAULT_BACK_OFF_RATE = 10; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FailureCacheValue.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FailureCacheValue.java index 98137aea12..c76e183b0a 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FailureCacheValue.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FailureCacheValue.java @@ -26,14 +26,15 @@ */ package org.apache.http.impl.client.cache; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * The error count with a creation timestamp and its associated key. * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class FailureCacheValue { private final long creationTimeInNanos; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResource.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResource.java index eef9c9ab9d..ecf6ffce06 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResource.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResource.java @@ -31,7 +31,8 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.Resource; /** @@ -39,7 +40,7 @@ * * @since 4.1 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class FileResource implements Resource { private static final long serialVersionUID = 4132244415919043397L; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java index f2c717c54c..b530eab1ae 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java @@ -31,7 +31,8 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.InputLimit; import org.apache.http.client.cache.Resource; import org.apache.http.client.cache.ResourceFactory; @@ -41,7 +42,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class FileResourceFactory implements ResourceFactory { private final File cacheDir; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResource.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResource.java index edf6b0f2f1..f46bd099a1 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResource.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResource.java @@ -29,7 +29,8 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.Resource; /** @@ -37,7 +38,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class HeapResource implements Resource { private static final long serialVersionUID = -2078599905620463394L; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java index 87a1b2a1d9..11506e24ea 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java @@ -30,7 +30,8 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.InputLimit; import org.apache.http.client.cache.Resource; import org.apache.http.client.cache.ResourceFactory; @@ -40,7 +41,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class HeapResourceFactory implements ResourceFactory { @Override diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java index b255d0f474..229bce681f 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java @@ -35,9 +35,7 @@ import java.nio.channels.FileChannel; import org.apache.http.HttpEntity; -import org.apache.http.annotation.Immutable; -@Immutable class IOUtils { static void consume(final HttpEntity entity) throws IOException { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ImmediateSchedulingStrategy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ImmediateSchedulingStrategy.java index 263c6b31a6..cb8c27eca4 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ImmediateSchedulingStrategy.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ImmediateSchedulingStrategy.java @@ -26,21 +26,22 @@ */ package org.apache.http.impl.client.cache; -import org.apache.http.annotation.ThreadSafe; -import org.apache.http.util.Args; - import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; +import org.apache.http.util.Args; + /** * Immediately schedules any incoming validation request. Relies on * {@link CacheConfig} to configure the used {@link java.util.concurrent.ThreadPoolExecutor}. * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class ImmediateSchedulingStrategy implements SchedulingStrategy { private final ExecutorService executor; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ManagedHttpCacheStorage.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ManagedHttpCacheStorage.java index 0a02658dea..cf65771da0 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ManagedHttpCacheStorage.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ManagedHttpCacheStorage.java @@ -33,7 +33,8 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.HttpCacheStorage; import org.apache.http.client.cache.HttpCacheUpdateCallback; @@ -70,7 +71,7 @@ * * @since 4.1 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class ManagedHttpCacheStorage implements HttpCacheStorage, Closeable { private final CacheMap entries; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/OptionsHttp11Response.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/OptionsHttp11Response.java index 2245360ea0..39fba6be5d 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/OptionsHttp11Response.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/OptionsHttp11Response.java @@ -36,7 +36,8 @@ import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.message.AbstractHttpMessage; import org.apache.http.message.BasicStatusLine; import org.apache.http.params.BasicHttpParams; @@ -46,7 +47,7 @@ * @since 4.1 */ @SuppressWarnings("deprecation") -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) final class OptionsHttp11Response extends AbstractHttpMessage implements HttpResponse { private final StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java index c86a039165..c17521b5c2 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/Proxies.java @@ -29,7 +29,6 @@ import java.lang.reflect.Proxy; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.util.Args; @@ -38,7 +37,6 @@ * * @since 4.3 */ -@NotThreadSafe class Proxies { public static CloseableHttpResponse enhanceResponse(final HttpResponse original) { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java index c74a607df1..a50dc8cacd 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java @@ -38,7 +38,8 @@ import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.methods.HttpRequestWrapper; @@ -52,7 +53,7 @@ /** * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class RequestProtocolCompliance { private final boolean weakETagOnPutDeleteAllowed; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResourceReference.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResourceReference.java index 4f9ac44200..e9f2cf9125 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResourceReference.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResourceReference.java @@ -29,12 +29,13 @@ import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.Resource; import org.apache.http.util.Args; -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class ResourceReference extends PhantomReference { private final Resource resource; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java index ae7a08b7ba..bbcb5d16b8 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java @@ -40,7 +40,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.utils.DateUtils; import org.apache.http.protocol.HTTP; @@ -50,7 +51,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class ResponseCachingPolicy { private static final String[] AUTH_CACHEABLE_PARAMS = { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java index bde392da70..c7e2785db9 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java @@ -39,7 +39,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.methods.HttpRequestWrapper; @@ -50,7 +51,7 @@ /** * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) class ResponseProtocolCompliance { private static final String UNEXPECTED_100_CONTINUE = "The incoming request did not contain a " diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java index 26f3c9da36..5b491c3a03 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProxyHandler.java @@ -34,7 +34,6 @@ import java.lang.reflect.Method; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; /** * A proxy class that can enhance an arbitrary {@link HttpResponse} with @@ -42,7 +41,6 @@ * * @since 4.3 */ -@NotThreadSafe class ResponseProxyHandler implements InvocationHandler { private static final Method CLOSE_METHOD; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java index 4cb520a9be..f02e608bf2 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java @@ -33,7 +33,6 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.cache.InputLimit; import org.apache.http.client.cache.Resource; import org.apache.http.client.cache.ResourceFactory; @@ -43,7 +42,6 @@ /** * @since 4.1 */ -@NotThreadSafe class SizeLimitedResponseReader { private final ResourceFactory resourceFactory; diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/CurrentWindowsCredentials.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/CurrentWindowsCredentials.java index 817499232d..335d0c9bed 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/CurrentWindowsCredentials.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/CurrentWindowsCredentials.java @@ -30,7 +30,8 @@ import java.io.Serializable; import java.security.Principal; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.Credentials; import com.sun.jna.platform.win32.Secur32.EXTENDED_NAME_FORMAT; @@ -44,7 +45,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class CurrentWindowsCredentials implements Credentials, Serializable, Principal { private static final long serialVersionUID = 4361166468529298169L; diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsCredentialsProvider.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsCredentialsProvider.java index aae9e229fc..f7921ea873 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsCredentialsProvider.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsCredentialsProvider.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.auth.win; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.client.CredentialsProvider; @@ -43,7 +44,7 @@ * * @since 4.4 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class WindowsCredentialsProvider implements CredentialsProvider { private final CredentialsProvider provider; diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java index 21bed6409e..724b935b62 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNTLMSchemeFactory.java @@ -27,7 +27,8 @@ package org.apache.http.impl.auth.win; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeProvider; import org.apache.http.client.config.AuthSchemes; @@ -42,7 +43,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class WindowsNTLMSchemeFactory implements AuthSchemeProvider { private final String servicePrincipalName; diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java index 3b0223f223..7e8b86612e 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java @@ -32,7 +32,6 @@ import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.Credentials; @@ -67,7 +66,6 @@ * * @since 4.4 */ -@NotThreadSafe public class WindowsNegotiateScheme extends AuthSchemeBase { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java index 29e5ffdb58..e719b8f925 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateSchemeFactory.java @@ -27,7 +27,8 @@ package org.apache.http.impl.auth.win; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeProvider; import org.apache.http.client.config.AuthSchemes; @@ -42,7 +43,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class WindowsNegotiateSchemeFactory implements AuthSchemeProvider { private final String servicePrincipalName; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/auth/params/AuthParams.java b/httpclient/src/main/java-deprecated/org/apache/http/auth/params/AuthParams.java index a7de770004..8312ae7d4e 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/auth/params/AuthParams.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/auth/params/AuthParams.java @@ -27,7 +27,8 @@ package org.apache.http.auth.params; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.Args; @@ -42,7 +43,7 @@ * and constructor parameters of * {@link org.apache.http.auth.AuthSchemeProvider}s. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public final class AuthParams { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/params/AuthPolicy.java b/httpclient/src/main/java-deprecated/org/apache/http/client/params/AuthPolicy.java index 768ddf991f..a4cad330d6 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/params/AuthPolicy.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/params/AuthPolicy.java @@ -27,8 +27,6 @@ package org.apache.http.client.params; -import org.apache.http.annotation.Immutable; - /** * Standard authentication schemes supported by HttpClient. * @@ -37,7 +35,6 @@ * @deprecated (4.3) use {@link org.apache.http.client.config.AuthSchemes}. */ @Deprecated -@Immutable public final class AuthPolicy { private AuthPolicy() { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/params/ClientParamBean.java b/httpclient/src/main/java-deprecated/org/apache/http/client/params/ClientParamBean.java index 99ba8510e0..7a84c77180 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/params/ClientParamBean.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/params/ClientParamBean.java @@ -31,7 +31,6 @@ import org.apache.http.Header; import org.apache.http.HttpHost; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.params.HttpAbstractParamBean; import org.apache.http.params.HttpParams; @@ -45,7 +44,6 @@ * @deprecated (4.3) use {@link org.apache.http.client.config.RequestConfig}. */ @Deprecated -@NotThreadSafe public class ClientParamBean extends HttpAbstractParamBean { public ClientParamBean (final HttpParams params) { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/params/CookiePolicy.java b/httpclient/src/main/java-deprecated/org/apache/http/client/params/CookiePolicy.java index e12ab426d3..505439edda 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/params/CookiePolicy.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/params/CookiePolicy.java @@ -27,8 +27,6 @@ package org.apache.http.client.params; -import org.apache.http.annotation.Immutable; - /** * Standard cookie specifications supported by HttpClient. * @@ -37,7 +35,6 @@ * @deprecated (4.3) use {@link org.apache.http.client.config.CookieSpecs}. */ @Deprecated -@Immutable public final class CookiePolicy { /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/params/HttpClientParams.java b/httpclient/src/main/java-deprecated/org/apache/http/client/params/HttpClientParams.java index c27cb7f939..50a12f95ab 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/params/HttpClientParams.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/params/HttpClientParams.java @@ -26,7 +26,6 @@ */ package org.apache.http.client.params; -import org.apache.http.annotation.Immutable; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.util.Args; @@ -39,7 +38,6 @@ * @deprecated (4.3) use {@link org.apache.http.client.config.RequestConfig} */ @Deprecated -@Immutable public class HttpClientParams { private HttpClientParams() { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContextConfigurer.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContextConfigurer.java index 39645ec402..6476a6bd25 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContextConfigurer.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContextConfigurer.java @@ -27,7 +27,6 @@ package org.apache.http.client.protocol; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthSchemeRegistry; import org.apache.http.client.CookieStore; import org.apache.http.client.CredentialsProvider; @@ -42,7 +41,6 @@ * * @deprecated (4.3) use {@link HttpClientContext} */ -@NotThreadSafe @Deprecated public class ClientContextConfigurer implements ClientContext { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java index b5ef5ad647..942a9cd6f7 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestProxyAuthentication.java @@ -31,7 +31,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthState; import org.apache.http.conn.HttpRoutedConnection; @@ -49,7 +50,7 @@ * @deprecated (4.3) use {@link org.apache.http.impl.auth.HttpAuthenticator}. */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestProxyAuthentication extends RequestAuthenticationBase { public RequestProxyAuthentication() { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java index 263ff57079..78f75d9386 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestTargetAuthentication.java @@ -31,7 +31,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthState; import org.apache.http.protocol.HttpContext; @@ -46,7 +47,7 @@ * @deprecated (4.3) use {@link org.apache.http.impl.auth.HttpAuthenticator}. */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestTargetAuthentication extends RequestAuthenticationBase { public RequestTargetAuthentication() { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java index 23322e8a8a..2a4ec3d673 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ResponseAuthCache.java @@ -35,7 +35,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthState; import org.apache.http.client.AuthCache; @@ -57,7 +58,7 @@ * * @deprecated (4.2) use {@link org.apache.http.client.AuthenticationStrategy} */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class ResponseAuthCache implements HttpResponseInterceptor { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/utils/JdkIdn.java b/httpclient/src/main/java-deprecated/org/apache/http/client/utils/JdkIdn.java index 99898b8276..427fcf89c1 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/utils/JdkIdn.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/utils/JdkIdn.java @@ -29,7 +29,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * Uses the java.net.IDN class through reflection. @@ -38,7 +39,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class JdkIdn implements Idn { private final Method toUnicode; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Punycode.java b/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Punycode.java index 2d17f3459d..58eb674c1c 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Punycode.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Punycode.java @@ -26,7 +26,8 @@ */ package org.apache.http.client.utils; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * Facade that provides conversion between Unicode and Punycode domain names. @@ -36,7 +37,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class Punycode { private static final Idn impl; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Rfc3492Idn.java b/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Rfc3492Idn.java index 29dabc4719..66ff45a398 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Rfc3492Idn.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/utils/Rfc3492Idn.java @@ -28,7 +28,8 @@ import java.util.StringTokenizer; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * Implementation from pseudo code in RFC 3492. @@ -37,7 +38,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class Rfc3492Idn implements Idn { private static final int base = 36; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java index 9fa2c331c1..6b64f37575 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicEofSensorWatcher.java @@ -29,7 +29,6 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.util.Args; /** @@ -41,7 +40,6 @@ * @deprecated (4.3) do not use. */ @Deprecated -@NotThreadSafe public class BasicEofSensorWatcher implements EofSensorWatcher { /** The connection to auto-release. */ diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java index 24dca916b1..93765e7eb1 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java @@ -32,7 +32,6 @@ import java.net.SocketException; import org.apache.http.HttpEntity; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.util.Args; import org.apache.http.util.EntityUtils; @@ -48,7 +47,6 @@ * @deprecated (4.3) do not use. */ @Deprecated -@NotThreadSafe public class BasicManagedEntity extends HttpEntityWrapper implements ConnectionReleaseTrigger, EofSensorWatcher { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java index 7ce6e05002..92a6258d0f 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/MultihomePlainSocketFactory.java @@ -37,7 +37,8 @@ import java.util.Collections; import java.util.List; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.scheme.SocketFactory; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; @@ -57,7 +58,7 @@ * {@link org.apache.http.conn.scheme.SchemeSocketFactory} interface. */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class MultihomePlainSocketFactory implements SocketFactory { /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParamBean.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParamBean.java index 2dd56a0571..d05d4617ec 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParamBean.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParamBean.java @@ -27,7 +27,6 @@ package org.apache.http.conn.params; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.params.HttpAbstractParamBean; import org.apache.http.params.HttpParams; @@ -40,7 +39,6 @@ * * @deprecated (4.1) use configuration methods of the specific connection manager implementation. */ -@NotThreadSafe @Deprecated public class ConnManagerParamBean extends HttpAbstractParamBean { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java index 3c4ddfb87b..0529aefda4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnManagerParams.java @@ -26,7 +26,8 @@ */ package org.apache.http.conn.params; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.params.HttpParams; import org.apache.http.util.Args; @@ -42,7 +43,7 @@ * @deprecated (4.1) use configuration methods of the specific connection manager implementation. */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class ConnManagerParams implements ConnManagerPNames { /** The default maximum number of connections allowed overall */ diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java index 241424f5b7..68e052f6ee 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnPerRouteBean.java @@ -29,7 +29,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.util.Args; @@ -44,7 +45,7 @@ * @deprecated (4.2) use {@link org.apache.http.pool.ConnPoolControl} */ @Deprecated -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public final class ConnPerRouteBean implements ConnPerRoute { /** The default maximum number of connections allowed per host */ diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParamBean.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParamBean.java index f574c7156a..e75c8c470c 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParamBean.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParamBean.java @@ -30,7 +30,6 @@ import java.net.InetAddress; import org.apache.http.HttpHost; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.params.HttpAbstractParamBean; import org.apache.http.params.HttpParams; @@ -45,7 +44,6 @@ * @deprecated (4.3) use {@link org.apache.http.client.config.RequestConfig}. */ @Deprecated -@NotThreadSafe public class ConnRouteParamBean extends HttpAbstractParamBean { public ConnRouteParamBean (final HttpParams params) { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParams.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParams.java index c4a9bc1deb..d28eb68411 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParams.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/params/ConnRouteParams.java @@ -29,7 +29,8 @@ import java.net.InetAddress; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.params.HttpParams; import org.apache.http.util.Args; @@ -43,7 +44,7 @@ * @deprecated (4.3) use {@link org.apache.http.client.config.RequestConfig}. */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class ConnRouteParams implements ConnRoutePNames { /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java index a6973b1690..f17415232e 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/scheme/PlainSocketFactory.java @@ -34,7 +34,8 @@ import java.net.SocketTimeoutException; import java.net.UnknownHostException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; @@ -47,7 +48,7 @@ * * @deprecated (4.3) use {@link org.apache.http.conn.socket.PlainConnectionSocketFactory} */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class PlainSocketFactory implements SocketFactory, SchemeSocketFactory { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java index c54db0c52a..fec0ca08e5 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContextBuilder.java @@ -51,8 +51,6 @@ import javax.net.ssl.X509KeyManager; import javax.net.ssl.X509TrustManager; -import org.apache.http.annotation.NotThreadSafe; - /** * Builder for {@link SSLContext} instances. * @@ -60,7 +58,6 @@ * * @deprecated (4.4) use {@link org.apache.http.ssl.SSLContextBuilder}. */ -@NotThreadSafe @Deprecated public class SSLContextBuilder { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContexts.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContexts.java index 26ab3e500e..e0a482eaaf 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContexts.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLContexts.java @@ -32,7 +32,8 @@ import javax.net.ssl.SSLContext; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * {@link SSLContext} factory methods. @@ -41,7 +42,7 @@ * * @deprecated (4.4) use {@link org.apache.http.ssl.SSLContexts}. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class SSLContexts { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java index 03fbe68017..8c7fee5a55 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java @@ -44,7 +44,8 @@ import javax.net.ssl.SSLSocket; import org.apache.http.HttpHost; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.HttpInetSocketAddress; import org.apache.http.conn.scheme.HostNameResolver; @@ -140,7 +141,7 @@ * * @deprecated (4.3) use {@link SSLConnectionSocketFactory}. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) @Deprecated public class SSLSocketFactory implements LayeredConnectionSocketFactory, SchemeLayeredSocketFactory, LayeredSchemeSocketFactory, LayeredSocketFactory { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/cookie/params/CookieSpecParamBean.java b/httpclient/src/main/java-deprecated/org/apache/http/cookie/params/CookieSpecParamBean.java index ea6a9299e1..917c054fde 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/cookie/params/CookieSpecParamBean.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/cookie/params/CookieSpecParamBean.java @@ -29,7 +29,6 @@ import java.util.Collection; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.params.HttpAbstractParamBean; import org.apache.http.params.HttpParams; @@ -44,7 +43,6 @@ * org.apache.http.cookie.CookieSpecProvider}s. */ @Deprecated -@NotThreadSafe public class CookieSpecParamBean extends HttpAbstractParamBean { public CookieSpecParamBean (final HttpParams params) { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java index c3af00dff2..7f020749a4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractAuthenticationHandler.java @@ -40,7 +40,8 @@ import org.apache.http.FormattedHeader; import org.apache.http.Header; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeRegistry; import org.apache.http.auth.AuthenticationException; @@ -61,7 +62,7 @@ * @deprecated (4.2) use {@link org.apache.http.client.AuthenticationStrategy} */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public abstract class AbstractAuthenticationHandler implements AuthenticationHandler { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java index f64fa8bb0b..35a669fccb 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AbstractHttpClient.java @@ -38,8 +38,8 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponseInterceptor; -import org.apache.http.annotation.GuardedBy; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthSchemeRegistry; import org.apache.http.client.AuthenticationHandler; import org.apache.http.client.AuthenticationStrategy; @@ -194,85 +194,30 @@ * * @deprecated (4.3) use {@link HttpClientBuilder}. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) @Deprecated public abstract class AbstractHttpClient extends CloseableHttpClient { private final Log log = LogFactory.getLog(getClass()); - /** The parameters. */ - @GuardedBy("this") private HttpParams defaultParams; - - /** The request executor. */ - @GuardedBy("this") private HttpRequestExecutor requestExec; - - /** The connection manager. */ - @GuardedBy("this") private ClientConnectionManager connManager; - - /** The connection re-use strategy. */ - @GuardedBy("this") private ConnectionReuseStrategy reuseStrategy; - - /** The connection keep-alive strategy. */ - @GuardedBy("this") private ConnectionKeepAliveStrategy keepAliveStrategy; - - /** The cookie spec registry. */ - @GuardedBy("this") private CookieSpecRegistry supportedCookieSpecs; - - /** The authentication scheme registry. */ - @GuardedBy("this") private AuthSchemeRegistry supportedAuthSchemes; - - /** The HTTP protocol processor and its immutable copy. */ - @GuardedBy("this") private BasicHttpProcessor mutableProcessor; - - @GuardedBy("this") private ImmutableHttpProcessor protocolProcessor; - - /** The request retry handler. */ - @GuardedBy("this") private HttpRequestRetryHandler retryHandler; - - /** The redirect handler. */ - @GuardedBy("this") private RedirectStrategy redirectStrategy; - - /** The target authentication handler. */ - @GuardedBy("this") private AuthenticationStrategy targetAuthStrategy; - - /** The proxy authentication handler. */ - @GuardedBy("this") private AuthenticationStrategy proxyAuthStrategy; - - /** The cookie store. */ - @GuardedBy("this") private CookieStore cookieStore; - - /** The credentials provider. */ - @GuardedBy("this") private CredentialsProvider credsProvider; - - /** The route planner. */ - @GuardedBy("this") private HttpRoutePlanner routePlanner; - - /** The user token handler. */ - @GuardedBy("this") private UserTokenHandler userTokenHandler; - - /** The connection backoff strategy. */ - @GuardedBy("this") private ConnectionBackoffStrategy connectionBackoffStrategy; - - /** The backoff manager. */ - @GuardedBy("this") private BackoffManager backoffManager; /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java index 2ff4ccf4d7..f72ae07f62 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java @@ -37,7 +37,8 @@ import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthOption; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthScope; @@ -56,7 +57,7 @@ /** * @deprecated (4.2) do not use */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated class AuthenticationStrategyAdaptor implements AuthenticationStrategy { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java index 272872a67b..5c0b864023 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AutoRetryHttpClient.java @@ -36,7 +36,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.ServiceUnavailableRetryStrategy; @@ -56,7 +57,7 @@ * @deprecated (4.3) use {@link HttpClientBuilder}. */ @Deprecated -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class AutoRetryHttpClient implements HttpClient { private final HttpClient backend; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java index 65f80d25a7..ea57a789a1 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ClientParamsStack.java @@ -27,7 +27,6 @@ package org.apache.http.impl.client; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.params.AbstractHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.util.Args; @@ -69,7 +68,6 @@ * @deprecated (4.3) use configuration classes provided 'org.apache.http.config' * and 'org.apache.http.client.config' */ -@NotThreadSafe @Deprecated public class ClientParamsStack extends AbstractHttpParams { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java index aa3fcec7a4..649d359276 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java @@ -36,7 +36,6 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.util.EntityUtils; @@ -44,7 +43,6 @@ * @since 4.3 */ @Deprecated -@NotThreadSafe class CloseableHttpResponseProxy implements InvocationHandler { private final static Constructor CONSTRUCTOR; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ContentEncodingHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ContentEncodingHttpClient.java index 4f1bd33ed8..7841064547 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ContentEncodingHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/ContentEncodingHttpClient.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.client; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.protocol.RequestAcceptEncoding; import org.apache.http.client.protocol.ResponseContentEncoding; import org.apache.http.conn.ClientConnectionManager; @@ -50,7 +51,7 @@ * @deprecated (4.2) use {@link HttpClientBuilder} */ @Deprecated -@ThreadSafe // since DefaultHttpClient is +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) // since DefaultHttpClient is public class ContentEncodingHttpClient extends DefaultHttpClient { /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultHttpClient.java index e64b008bf0..389bc3a500 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultHttpClient.java @@ -28,7 +28,8 @@ package org.apache.http.impl.client; import org.apache.http.HttpVersion; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.protocol.RequestAddCookies; import org.apache.http.client.protocol.RequestAuthCache; import org.apache.http.client.protocol.RequestClientConnControl; @@ -112,7 +113,7 @@ * * @deprecated (4.3) use {@link HttpClientBuilder} see also {@link CloseableHttpClient}. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) @Deprecated public class DefaultHttpClient extends AbstractHttpClient { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java index 14ce013e1e..1491a09308 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java @@ -33,7 +33,8 @@ import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AUTH; import org.apache.http.auth.MalformedChallengeException; import org.apache.http.auth.params.AuthPNames; @@ -49,7 +50,7 @@ * @deprecated (4.2) use {@link ProxyAuthenticationStrategy} */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultProxyAuthenticationHandler extends AbstractAuthenticationHandler { public DefaultProxyAuthenticationHandler() { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java index 228b69096d..0c1e7b70b0 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectHandler.java @@ -38,7 +38,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.CircularRedirectException; import org.apache.http.client.RedirectHandler; import org.apache.http.client.methods.HttpGet; @@ -58,7 +59,7 @@ * * @deprecated (4.1) use {@link DefaultRedirectStrategy}. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class DefaultRedirectHandler implements RedirectHandler { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java index d87090fc33..41ef7ed1dc 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java @@ -32,7 +32,8 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.RedirectHandler; import org.apache.http.client.RedirectStrategy; import org.apache.http.client.methods.HttpGet; @@ -43,7 +44,7 @@ /** * @deprecated (4.1) do not use */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated class DefaultRedirectStrategyAdaptor implements RedirectStrategy { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java index ed233b2931..45cb9988ef 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java @@ -45,7 +45,6 @@ import org.apache.http.NoHttpResponseException; import org.apache.http.ProtocolException; import org.apache.http.ProtocolVersion; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthProtocolState; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthState; @@ -132,7 +131,6 @@ * @deprecated (4.3) */ @Deprecated -@NotThreadSafe // e.g. managedConn public class DefaultRequestDirector implements RequestDirector { private final Log log; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java index c47f9e0849..b4499c9577 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java @@ -33,7 +33,8 @@ import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AUTH; import org.apache.http.auth.MalformedChallengeException; import org.apache.http.auth.params.AuthPNames; @@ -49,7 +50,7 @@ * @deprecated (4.2) use {@link TargetAuthenticationStrategy} */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultTargetAuthenticationHandler extends AbstractAuthenticationHandler { public DefaultTargetAuthenticationHandler() { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/RoutedRequest.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/RoutedRequest.java index 43a0a80a04..4c54403028 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/RoutedRequest.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/RoutedRequest.java @@ -27,7 +27,6 @@ package org.apache.http.impl.client; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.routing.HttpRoute; /** @@ -38,11 +37,10 @@ * @deprecated (4.3) do not use. */ @Deprecated -@NotThreadSafe // RequestWrapper is @NotThreadSafe public class RoutedRequest { protected final RequestWrapper request; // @NotThreadSafe - protected final HttpRoute route; // @Immutable + protected final HttpRoute route; // @Contract(threading = ThreadingBehavior.IMMUTABLE) /** * Creates a new routed request. diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java index 0d3c58186b..b8cecf22ce 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java @@ -30,7 +30,8 @@ import java.net.ProxySelector; import org.apache.http.ConnectionReuseStrategy; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.impl.DefaultConnectionReuseStrategy; @@ -104,7 +105,7 @@ * * @deprecated (4.3) use {@link HttpClientBuilder} */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) @Deprecated public class SystemDefaultHttpClient extends DefaultHttpClient { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/TunnelRefusedException.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/TunnelRefusedException.java index 0a6f134dd1..b1e634e294 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/TunnelRefusedException.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/TunnelRefusedException.java @@ -29,7 +29,6 @@ import org.apache.http.HttpException; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; /** * Signals that the tunnel request was rejected by the proxy host. @@ -39,7 +38,6 @@ * @deprecated (4.3) reserved for internal use. */ @Deprecated -@Immutable public class TunnelRefusedException extends HttpException { private static final long serialVersionUID = -8646722842745617323L; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java index 5a1827af1b..3f2a420de4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/AbstractClientConnAdapter.java @@ -40,7 +40,6 @@ import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ManagedClientConnection; import org.apache.http.conn.OperatedClientConnection; @@ -70,7 +69,6 @@ * @deprecated (4.2) do not use */ @Deprecated -@NotThreadSafe public abstract class AbstractClientConnAdapter implements ManagedClientConnection, HttpContext { /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java index 9e424a48c9..3e158ab23b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java @@ -34,8 +34,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpClientConnection; -import org.apache.http.annotation.GuardedBy; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionRequest; @@ -66,7 +66,7 @@ * * @deprecated (4.3) use {@link BasicHttpClientConnectionManager}. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public class BasicClientConnectionManager implements ClientConnectionManager { @@ -86,15 +86,12 @@ public class BasicClientConnectionManager implements ClientConnectionManager { private final ClientConnectionOperator connOperator; /** The one and only entry in this pool. */ - @GuardedBy("this") private HttpPoolEntry poolEntry; /** The currently issued managed connection, if any. */ - @GuardedBy("this") private ManagedClientConnectionImpl conn; /** Indicates whether this connection manager is shut down. */ - @GuardedBy("this") private volatile boolean shutdown; /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java index 5a29784c4f..081f0671c2 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java @@ -44,9 +44,8 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseFactory; -import org.apache.http.annotation.NotThreadSafe; -import org.apache.http.conn.OperatedClientConnection; import org.apache.http.conn.ManagedHttpClientConnection; +import org.apache.http.conn.OperatedClientConnection; import org.apache.http.impl.SocketHttpClientConnection; import org.apache.http.io.HttpMessageParser; import org.apache.http.io.SessionInputBuffer; @@ -64,7 +63,6 @@ * * @deprecated (4.3) use {@link ManagedHttpClientConnectionFactory}. */ -@NotThreadSafe // connSecure, targetHost @Deprecated public class DefaultClientConnection extends SocketHttpClientConnection implements OperatedClientConnection, ManagedHttpClientConnection, HttpContext { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java index ee14079f11..5eaac13527 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java @@ -37,7 +37,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.protocol.ClientContext; import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ConnectTimeoutException; @@ -86,13 +87,13 @@ * @deprecated (4.3) use {@link PoolingHttpClientConnectionManager}. */ @Deprecated -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class DefaultClientConnectionOperator implements ClientConnectionOperator { private final Log log = LogFactory.getLog(getClass()); /** The scheme registry for looking up socket factories. */ - protected final SchemeRegistry schemeRegistry; // @ThreadSafe + protected final SchemeRegistry schemeRegistry; // @Contract(threading = ThreadingBehavior.SAFE) /** the custom-configured DNS lookup mechanism. */ protected final DnsResolver dnsResolver; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java index 650c202494..e0ac52eef9 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultHttpRoutePlanner.java @@ -33,7 +33,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.params.ConnRouteParams; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.routing.HttpRoutePlanner; @@ -61,12 +62,12 @@ * * @deprecated (4.3) use {@link DefaultRoutePlanner} */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public class DefaultHttpRoutePlanner implements HttpRoutePlanner { /** The scheme registry. */ - protected final SchemeRegistry schemeRegistry; // class is @ThreadSafe + protected final SchemeRegistry schemeRegistry; // class is @Contract(threading = ThreadingBehavior.SAFE) /** * Creates a new default route planner. diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultResponseParser.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultResponseParser.java index 456c2953a4..732c9e8803 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultResponseParser.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultResponseParser.java @@ -37,7 +37,8 @@ import org.apache.http.NoHttpResponseException; import org.apache.http.ProtocolException; import org.apache.http.StatusLine; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.impl.io.AbstractMessageParser; import org.apache.http.io.SessionInputBuffer; import org.apache.http.message.LineParser; @@ -62,7 +63,7 @@ * @deprecated (4.2) use {@link DefaultHttpResponseParser} */ @Deprecated -@ThreadSafe // no public methods +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class DefaultResponseParser extends AbstractMessageParser { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java index 4708306708..a0b37ae13d 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java @@ -29,7 +29,8 @@ import java.io.IOException; import org.apache.http.Consts; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.io.EofSensor; import org.apache.http.io.HttpTransportMetrics; import org.apache.http.io.SessionInputBuffer; @@ -42,7 +43,7 @@ * * @deprecated (4.3) no longer used. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class LoggingSessionInputBuffer implements SessionInputBuffer, EofSensor { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java index a4e9912710..8c552e11c7 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionOutputBuffer.java @@ -29,7 +29,8 @@ import java.io.IOException; import org.apache.http.Consts; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.io.HttpTransportMetrics; import org.apache.http.io.SessionOutputBuffer; import org.apache.http.util.CharArrayBuffer; @@ -39,7 +40,7 @@ * @since 4.0 * @deprecated (4.3) no longer used. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class LoggingSessionOutputBuffer implements SessionOutputBuffer { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java index 7b5b70f92a..dea2e11ff2 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ManagedClientConnectionImpl.java @@ -41,7 +41,6 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ManagedClientConnection; @@ -59,7 +58,6 @@ * @deprecated (4.3) use {@link ManagedHttpClientConnectionFactory}. */ @Deprecated -@NotThreadSafe class ManagedClientConnectionImpl implements ManagedClientConnection { private final ClientConnectionManager manager; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java index a4e5f286a1..3e2fefbbb4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java @@ -34,7 +34,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionRequest; @@ -69,7 +70,7 @@ * @deprecated (4.3) use {@link PoolingHttpClientConnectionManager}. */ @Deprecated -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class PoolingClientConnectionManager implements ClientConnectionManager, ConnPoolControl { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java index 2fe96d1ff4..be08daac73 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java @@ -39,7 +39,6 @@ import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.params.ConnRouteParams; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.routing.HttpRoutePlanner; @@ -71,12 +70,11 @@ * * @deprecated (4.3) use {@link SystemDefaultRoutePlanner} */ -@NotThreadSafe // e.g [gs]etProxySelector() @Deprecated public class ProxySelectorRoutePlanner implements HttpRoutePlanner { /** The scheme registry. */ - protected final SchemeRegistry schemeRegistry; // @ThreadSafe + protected final SchemeRegistry schemeRegistry; // @Contract(threading = ThreadingBehavior.SAFE) /** The proxy selector to use, or {@code null} for system default. */ protected ProxySelector proxySelector; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SchemeRegistryFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SchemeRegistryFactory.java index 06105dd198..7290728c15 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SchemeRegistryFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SchemeRegistryFactory.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.conn; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; @@ -37,7 +38,7 @@ * * @deprecated (4.3) use {@link org.apache.http.impl.client.HttpClientBuilder}. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public final class SchemeRegistryFactory { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java index 774cf4a370..2861b9b690 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java @@ -32,8 +32,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.annotation.GuardedBy; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionRequest; @@ -61,7 +61,7 @@ * * @deprecated (4.2) use {@link BasicClientConnectionManager} */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public class SingleClientConnManager implements ClientConnectionManager { @@ -82,19 +82,15 @@ public class SingleClientConnManager implements ClientConnectionManager { protected final boolean alwaysShutDown; /** The one and only entry in this pool. */ - @GuardedBy("this") protected volatile PoolEntry uniquePoolEntry; /** The currently issued managed connection, if any. */ - @GuardedBy("this") protected volatile ConnAdapter managedConn; /** The time of the last connection release, or -1. */ - @GuardedBy("this") protected volatile long lastReleaseTime; /** The time the last released connection expires and shouldn't be reused. */ - @GuardedBy("this") protected volatile long connectionExpiresTime; /** Indicates whether this connection manager is shut down. */ diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java index c7e6243ca6..d9dfbfe2ba 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java @@ -38,7 +38,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.annotation.GuardedBy; import org.apache.http.conn.ConnectionPoolTimeoutException; import org.apache.http.conn.OperatedClientConnection; import org.apache.http.conn.routing.HttpRoute; @@ -66,12 +65,8 @@ public abstract class AbstractConnPool { */ protected final Lock poolLock; - /** References to issued connections */ - @GuardedBy("poolLock") protected Set leasedConnections; - /** The current total number of connections. */ - @GuardedBy("poolLock") protected int numConnections; /** Indicates whether this pool is shut down. */ diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/BasicPoolEntryRef.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/BasicPoolEntryRef.java index 2220380800..c831f8d286 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/BasicPoolEntryRef.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/BasicPoolEntryRef.java @@ -45,7 +45,7 @@ public class BasicPoolEntryRef extends WeakReference { /** The planned route of the entry. */ - private final HttpRoute route; // HttpRoute is @Immutable + private final HttpRoute route; // HttpRoute is @Contract(threading = ThreadingBehavior.IMMUTABLE) /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java index 5bda67c36f..74f11189c4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java @@ -31,7 +31,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionRequest; @@ -66,14 +67,14 @@ * * @deprecated (4.2) use {@link org.apache.http.impl.conn.PoolingHttpClientConnectionManager} */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) @Deprecated public class ThreadSafeClientConnManager implements ClientConnectionManager { private final Log log; /** The schemes supported by this connection manager. */ - protected final SchemeRegistry schemeRegistry; // @ThreadSafe + protected final SchemeRegistry schemeRegistry; // @Contract(threading = ThreadingBehavior.SAFE) protected final AbstractConnPool connectionPool; @@ -81,7 +82,7 @@ public class ThreadSafeClientConnManager implements ClientConnectionManager { protected final ConnPoolByRoute pool; /** The operator for opening and updating connections. */ - protected final ClientConnectionOperator connOperator; // DefaultClientConnectionOperator is @ThreadSafe + protected final ClientConnectionOperator connOperator; // DefaultClientConnectionOperator is @Contract(threading = ThreadingBehavior.SAFE) protected final ConnPerRouteBean connPerRoute; @@ -206,7 +207,7 @@ protected ConnPoolByRoute createConnectionPool(final long connTTL, final TimeUni protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry schreg) { - return new DefaultClientConnectionOperator(schreg);// @ThreadSafe + return new DefaultClientConnectionOperator(schreg);// @Contract(threading = ThreadingBehavior.SAFE) } @Override diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpec.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpec.java index a21da60b32..5f829a5758 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpec.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpec.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * 'Meta' cookie specification that picks up a cookie policy based on @@ -37,7 +38,7 @@ * * @since 4.0 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public class BestMatchSpec extends DefaultCookieSpec { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java index 7ad7f63271..e87f3d018d 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java @@ -29,7 +29,8 @@ import java.util.Collection; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecFactory; import org.apache.http.cookie.CookieSpecProvider; @@ -46,7 +47,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class BestMatchSpecFactory implements CookieSpecFactory, CookieSpecProvider { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java index 46d834d5e0..fb559f7d31 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpec.java @@ -36,7 +36,8 @@ import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.NameValuePair; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.utils.DateUtils; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieAttributeHandler; @@ -61,7 +62,7 @@ * @since 4.0 */ @Deprecated -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class BrowserCompatSpec extends CookieSpecBase { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpecFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpecFactory.java index a89908f22f..7cb0f8895a 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpecFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatSpecFactory.java @@ -29,7 +29,8 @@ import java.util.Collection; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecFactory; import org.apache.http.cookie.CookieSpecProvider; @@ -46,7 +47,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class BrowserCompatSpecFactory implements CookieSpecFactory, CookieSpecProvider { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java index 387259ca8b..0a68578fdd 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BrowserCompatVersionAttributeHandler.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.MalformedCookieException; @@ -42,7 +43,7 @@ * @since 4.3 */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BrowserCompatVersionAttributeHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateParseException.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateParseException.java index e6d07bcba9..aa2faec817 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateParseException.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateParseException.java @@ -27,8 +27,6 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; - /** * An exception to indicate an error parsing a date string. * @@ -40,7 +38,6 @@ * @deprecated (4.3) no longer used. */ @Deprecated -@Immutable public class DateParseException extends Exception { private static final long serialVersionUID = 4417696455000643370L; diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateUtils.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateUtils.java index 57e0bd1de1..22f5d06220 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateUtils.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/DateUtils.java @@ -30,8 +30,6 @@ import java.util.Date; import java.util.TimeZone; -import org.apache.http.annotation.Immutable; - /** * A utility class for parsing and formatting HTTP dates as used in cookies and * other headers. This class handles dates as defined by RFC 2616 section @@ -43,7 +41,6 @@ * @deprecated (4.3) Use {@link org.apache.http.client.utils.DateUtils}. */ @Deprecated -@Immutable public final class DateUtils { /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/IgnoreSpecFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/IgnoreSpecFactory.java index 91052c1fff..835badf862 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/IgnoreSpecFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/IgnoreSpecFactory.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecFactory; import org.apache.http.cookie.CookieSpecProvider; @@ -41,7 +42,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class IgnoreSpecFactory implements CookieSpecFactory, CookieSpecProvider { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/NetscapeDraftSpecFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/NetscapeDraftSpecFactory.java index e5e72d82dd..a8a6f04133 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/NetscapeDraftSpecFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/NetscapeDraftSpecFactory.java @@ -29,7 +29,8 @@ import java.util.Collection; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecFactory; import org.apache.http.cookie.CookieSpecProvider; @@ -46,7 +47,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class NetscapeDraftSpecFactory implements CookieSpecFactory, CookieSpecProvider { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixListParser.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixListParser.java index 210956c75e..4c04586218 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixListParser.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixListParser.java @@ -29,7 +29,8 @@ import java.io.IOException; import java.io.Reader; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.PublicSuffixList; /** @@ -40,7 +41,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class PublicSuffixListParser { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2109SpecFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2109SpecFactory.java index 278e24000b..e6a3f79bad 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2109SpecFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2109SpecFactory.java @@ -29,7 +29,8 @@ import java.util.Collection; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecFactory; import org.apache.http.cookie.CookieSpecProvider; @@ -46,7 +47,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class RFC2109SpecFactory implements CookieSpecFactory, CookieSpecProvider { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2965SpecFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2965SpecFactory.java index 95ba80142b..7ccfb97bb7 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2965SpecFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/RFC2965SpecFactory.java @@ -29,7 +29,8 @@ import java.util.Collection; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecFactory; import org.apache.http.cookie.CookieSpecProvider; @@ -46,7 +47,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class RFC2965SpecFactory implements CookieSpecFactory, CookieSpecProvider { diff --git a/httpclient/src/main/java/org/apache/http/auth/AUTH.java b/httpclient/src/main/java/org/apache/http/auth/AUTH.java index 8ae4545336..69fcc9ca9c 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AUTH.java +++ b/httpclient/src/main/java/org/apache/http/auth/AUTH.java @@ -27,15 +27,12 @@ package org.apache.http.auth; -import org.apache.http.annotation.Immutable; - /** * Constants and static helpers related to the HTTP authentication. * * * @since 4.0 */ -@Immutable public final class AUTH { /** diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthOption.java b/httpclient/src/main/java/org/apache/http/auth/AuthOption.java index 21f0bc965a..ff5f5e9d23 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthOption.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthOption.java @@ -26,13 +26,14 @@ */ package org.apache.http.auth; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; /** * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class AuthOption { private final AuthScheme authScheme; diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java b/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java index d3dcddc5bb..30a578eee4 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java @@ -33,7 +33,8 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpRequest; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.config.Lookup; import org.apache.http.params.HttpParams; import org.apache.http.protocol.ExecutionContext; @@ -48,7 +49,7 @@ * * @deprecated (4.3) use {@link org.apache.http.config.Registry} */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public final class AuthSchemeRegistry implements Lookup { diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthScope.java b/httpclient/src/main/java/org/apache/http/auth/AuthScope.java index 548854009c..46f9cc4850 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthScope.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthScope.java @@ -29,7 +29,8 @@ import java.util.Locale; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.LangUtils; @@ -42,7 +43,7 @@ *

* @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class AuthScope { /** diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthState.java b/httpclient/src/main/java/org/apache/http/auth/AuthState.java index 9b932e78ec..64febf36f7 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthState.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthState.java @@ -28,7 +28,6 @@ import java.util.Queue; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.util.Args; /** @@ -36,7 +35,6 @@ * * @since 4.0 */ -@NotThreadSafe public class AuthState { /** Actual state of authentication protocol */ diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthenticationException.java b/httpclient/src/main/java/org/apache/http/auth/AuthenticationException.java index 8d8e34c630..d8e2aa3097 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthenticationException.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthenticationException.java @@ -27,7 +27,6 @@ package org.apache.http.auth; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; /** * Signals a failure in authentication process @@ -35,7 +34,6 @@ * * @since 4.0 */ -@Immutable public class AuthenticationException extends ProtocolException { private static final long serialVersionUID = -6794031905674764776L; diff --git a/httpclient/src/main/java/org/apache/http/auth/BasicUserPrincipal.java b/httpclient/src/main/java/org/apache/http/auth/BasicUserPrincipal.java index 92bf4e6c9b..d52538c480 100644 --- a/httpclient/src/main/java/org/apache/http/auth/BasicUserPrincipal.java +++ b/httpclient/src/main/java/org/apache/http/auth/BasicUserPrincipal.java @@ -29,7 +29,8 @@ import java.io.Serializable; import java.security.Principal; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.LangUtils; @@ -38,7 +39,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class BasicUserPrincipal implements Principal, Serializable { private static final long serialVersionUID = -2266305184969850467L; diff --git a/httpclient/src/main/java/org/apache/http/auth/InvalidCredentialsException.java b/httpclient/src/main/java/org/apache/http/auth/InvalidCredentialsException.java index e357241c1c..44812bd7f0 100644 --- a/httpclient/src/main/java/org/apache/http/auth/InvalidCredentialsException.java +++ b/httpclient/src/main/java/org/apache/http/auth/InvalidCredentialsException.java @@ -26,8 +26,6 @@ */ package org.apache.http.auth; -import org.apache.http.annotation.Immutable; - /** * Authentication credentials required to respond to a authentication * challenge are invalid @@ -35,7 +33,6 @@ * * @since 4.0 */ -@Immutable public class InvalidCredentialsException extends AuthenticationException { private static final long serialVersionUID = -4834003835215460648L; diff --git a/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java b/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java index 16d0c5bf05..1ff5a62b56 100644 --- a/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/KerberosCredentials.java @@ -29,7 +29,8 @@ import java.io.Serializable; import java.security.Principal; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.ietf.jgss.GSSCredential; /** @@ -37,7 +38,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class KerberosCredentials implements Credentials, Serializable { private static final long serialVersionUID = 487421613855550713L; diff --git a/httpclient/src/main/java/org/apache/http/auth/MalformedChallengeException.java b/httpclient/src/main/java/org/apache/http/auth/MalformedChallengeException.java index 172ba0c6ee..2d6d14be9f 100644 --- a/httpclient/src/main/java/org/apache/http/auth/MalformedChallengeException.java +++ b/httpclient/src/main/java/org/apache/http/auth/MalformedChallengeException.java @@ -27,7 +27,6 @@ package org.apache.http.auth; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; /** * Signals that authentication challenge is in some way invalid or @@ -36,7 +35,6 @@ * * @since 4.0 */ -@Immutable public class MalformedChallengeException extends ProtocolException { private static final long serialVersionUID = 814586927989932284L; diff --git a/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java b/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java index 430eb2d0b1..9dd3c069fc 100644 --- a/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/NTCredentials.java @@ -30,7 +30,8 @@ import java.security.Principal; import java.util.Locale; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.LangUtils; @@ -40,7 +41,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NTCredentials implements Credentials, Serializable { private static final long serialVersionUID = -7385699315228907265L; diff --git a/httpclient/src/main/java/org/apache/http/auth/NTUserPrincipal.java b/httpclient/src/main/java/org/apache/http/auth/NTUserPrincipal.java index 82999395ec..da0b41fa89 100644 --- a/httpclient/src/main/java/org/apache/http/auth/NTUserPrincipal.java +++ b/httpclient/src/main/java/org/apache/http/auth/NTUserPrincipal.java @@ -30,7 +30,8 @@ import java.security.Principal; import java.util.Locale; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.LangUtils; @@ -39,7 +40,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NTUserPrincipal implements Principal, Serializable { private static final long serialVersionUID = -6870169797924406894L; diff --git a/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java b/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java index b593b2472d..410a95c538 100644 --- a/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java +++ b/httpclient/src/main/java/org/apache/http/auth/UsernamePasswordCredentials.java @@ -29,7 +29,8 @@ import java.io.Serializable; import java.security.Principal; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.LangUtils; @@ -39,7 +40,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class UsernamePasswordCredentials implements Credentials, Serializable { private static final long serialVersionUID = 243343858802739403L; diff --git a/httpclient/src/main/java/org/apache/http/client/CircularRedirectException.java b/httpclient/src/main/java/org/apache/http/client/CircularRedirectException.java index 489aa72e04..e04e57834d 100644 --- a/httpclient/src/main/java/org/apache/http/client/CircularRedirectException.java +++ b/httpclient/src/main/java/org/apache/http/client/CircularRedirectException.java @@ -26,15 +26,12 @@ */ package org.apache.http.client; -import org.apache.http.annotation.Immutable; - /** * Signals a circular redirect * * * @since 4.0 */ -@Immutable public class CircularRedirectException extends RedirectException { private static final long serialVersionUID = 6830063487001091803L; diff --git a/httpclient/src/main/java/org/apache/http/client/ClientProtocolException.java b/httpclient/src/main/java/org/apache/http/client/ClientProtocolException.java index 8383eac478..b4efeab29f 100644 --- a/httpclient/src/main/java/org/apache/http/client/ClientProtocolException.java +++ b/httpclient/src/main/java/org/apache/http/client/ClientProtocolException.java @@ -28,14 +28,11 @@ import java.io.IOException; -import org.apache.http.annotation.Immutable; - /** * Signals an error in the HTTP protocol. * * @since 4.0 */ -@Immutable public class ClientProtocolException extends IOException { private static final long serialVersionUID = -5596590843227115865L; diff --git a/httpclient/src/main/java/org/apache/http/client/HttpResponseException.java b/httpclient/src/main/java/org/apache/http/client/HttpResponseException.java index 07e43776aa..38a8cb52d2 100644 --- a/httpclient/src/main/java/org/apache/http/client/HttpResponseException.java +++ b/httpclient/src/main/java/org/apache/http/client/HttpResponseException.java @@ -26,14 +26,11 @@ */ package org.apache.http.client; -import org.apache.http.annotation.Immutable; - /** * Signals a non 2xx HTTP response. * * @since 4.0 */ -@Immutable public class HttpResponseException extends ClientProtocolException { private static final long serialVersionUID = -7186627969477257933L; diff --git a/httpclient/src/main/java/org/apache/http/client/NonRepeatableRequestException.java b/httpclient/src/main/java/org/apache/http/client/NonRepeatableRequestException.java index 4f4befb2cf..ee70c21ad4 100644 --- a/httpclient/src/main/java/org/apache/http/client/NonRepeatableRequestException.java +++ b/httpclient/src/main/java/org/apache/http/client/NonRepeatableRequestException.java @@ -27,7 +27,6 @@ package org.apache.http.client; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; /** * Signals failure to retry the request due to non-repeatable request @@ -36,7 +35,6 @@ * * @since 4.0 */ -@Immutable public class NonRepeatableRequestException extends ProtocolException { private static final long serialVersionUID = 82685265288806048L; diff --git a/httpclient/src/main/java/org/apache/http/client/RedirectException.java b/httpclient/src/main/java/org/apache/http/client/RedirectException.java index cf2abacd0c..6bfa88b1b4 100644 --- a/httpclient/src/main/java/org/apache/http/client/RedirectException.java +++ b/httpclient/src/main/java/org/apache/http/client/RedirectException.java @@ -27,7 +27,6 @@ package org.apache.http.client; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; /** * Signals violation of HTTP specification caused by an invalid redirect @@ -35,7 +34,6 @@ * * @since 4.0 */ -@Immutable public class RedirectException extends ProtocolException { private static final long serialVersionUID = 4418824536372559326L; diff --git a/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java b/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java index 58f5d613e3..da7e26881c 100644 --- a/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java +++ b/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java @@ -27,14 +27,11 @@ package org.apache.http.client.config; -import org.apache.http.annotation.Immutable; - /** * Standard authentication schemes supported by HttpClient. * * @since 4.3 */ -@Immutable public final class AuthSchemes { /** diff --git a/httpclient/src/main/java/org/apache/http/client/config/CookieSpecs.java b/httpclient/src/main/java/org/apache/http/client/config/CookieSpecs.java index 86477f2661..3bb76a0300 100644 --- a/httpclient/src/main/java/org/apache/http/client/config/CookieSpecs.java +++ b/httpclient/src/main/java/org/apache/http/client/config/CookieSpecs.java @@ -27,14 +27,11 @@ package org.apache.http.client.config; -import org.apache.http.annotation.Immutable; - /** * Standard cookie specifications supported by HttpClient. * * @since 4.3 */ -@Immutable public final class CookieSpecs { /** diff --git a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java index 87f772ff61..38a0c732ce 100644 --- a/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java +++ b/httpclient/src/main/java/org/apache/http/client/config/RequestConfig.java @@ -31,14 +31,15 @@ import java.util.Collection; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * Immutable class encapsulating request configuration items. * The default setting for stale connection checking changed * to false, and the feature was deprecated starting with version 4.4. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestConfig implements Cloneable { public static final RequestConfig DEFAULT = new Builder().build(); diff --git a/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java b/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java index ce3dfe2fe3..3c966785c7 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java @@ -35,7 +35,6 @@ import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.entity.BasicHttpEntity; import org.apache.http.entity.ByteArrayEntity; @@ -63,7 +62,6 @@ * * @since 4.3 */ -@NotThreadSafe public class EntityBuilder { private String text; diff --git a/httpclient/src/main/java/org/apache/http/client/entity/LazyDecompressingInputStream.java b/httpclient/src/main/java/org/apache/http/client/entity/LazyDecompressingInputStream.java index db95ce8b4a..36b285c061 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/LazyDecompressingInputStream.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/LazyDecompressingInputStream.java @@ -29,12 +29,9 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.annotation.NotThreadSafe; - /** * Lazy init InputStream wrapper. */ -@NotThreadSafe class LazyDecompressingInputStream extends InputStream { private final InputStream wrappedStream; diff --git a/httpclient/src/main/java/org/apache/http/client/entity/UrlEncodedFormEntity.java b/httpclient/src/main/java/org/apache/http/client/entity/UrlEncodedFormEntity.java index 80bf86364d..29b5be1446 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/UrlEncodedFormEntity.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/UrlEncodedFormEntity.java @@ -31,7 +31,6 @@ import java.util.List; import org.apache.http.NameValuePair; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; @@ -43,7 +42,6 @@ * * @since 4.0 */ -@NotThreadSafe // AbstractHttpEntity is not thread-safe public class UrlEncodedFormEntity extends StringEntity { /** diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpDelete.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpDelete.java index 9b078a3eaf..58d07c03dd 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpDelete.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpDelete.java @@ -29,8 +29,6 @@ import java.net.URI; -import org.apache.http.annotation.NotThreadSafe; - /** * HTTP DELETE method *

@@ -46,7 +44,6 @@ * * @since 4.0 */ -@NotThreadSafe // HttpRequestBase is @NotThreadSafe public class HttpDelete extends HttpRequestBase { public final static String METHOD_NAME = "DELETE"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpEntityEnclosingRequestBase.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpEntityEnclosingRequestBase.java index 5efb828102..4fdf006c65 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpEntityEnclosingRequestBase.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpEntityEnclosingRequestBase.java @@ -30,7 +30,6 @@ import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.utils.CloneUtils; import org.apache.http.protocol.HTTP; @@ -40,7 +39,6 @@ * * @since 4.0 */ -@NotThreadSafe // HttpRequestBase is @NotThreadSafe public abstract class HttpEntityEnclosingRequestBase extends HttpRequestBase implements HttpEntityEnclosingRequest { diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpGet.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpGet.java index 35de2d3e41..e21539424d 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpGet.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpGet.java @@ -29,8 +29,6 @@ import java.net.URI; -import org.apache.http.annotation.NotThreadSafe; - /** * HTTP GET method. *

@@ -47,7 +45,6 @@ * * @since 4.0 */ -@NotThreadSafe public class HttpGet extends HttpRequestBase { public final static String METHOD_NAME = "GET"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpHead.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpHead.java index 4e4bd96675..bc17d95f4c 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpHead.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpHead.java @@ -29,8 +29,6 @@ import java.net.URI; -import org.apache.http.annotation.NotThreadSafe; - /** * HTTP HEAD method. *

@@ -50,7 +48,6 @@ * * @since 4.0 */ -@NotThreadSafe public class HttpHead extends HttpRequestBase { public final static String METHOD_NAME = "HEAD"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpOptions.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpOptions.java index 382eddac44..304ed4ab2f 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpOptions.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpOptions.java @@ -35,7 +35,6 @@ import org.apache.http.HeaderElement; import org.apache.http.HeaderIterator; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.util.Args; /** @@ -55,7 +54,6 @@ * * @since 4.0 */ -@NotThreadSafe public class HttpOptions extends HttpRequestBase { public final static String METHOD_NAME = "OPTIONS"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpPatch.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpPatch.java index 43153e4fd8..c5bea336fe 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpPatch.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpPatch.java @@ -29,8 +29,6 @@ import java.net.URI; -import org.apache.http.annotation.NotThreadSafe; - /** * HTTP PATCH method. *

@@ -50,7 +48,6 @@ * * @since 4.2 */ -@NotThreadSafe public class HttpPatch extends HttpEntityEnclosingRequestBase { public final static String METHOD_NAME = "PATCH"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpPost.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpPost.java index 410092e0d5..8a44bcae31 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpPost.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpPost.java @@ -29,8 +29,6 @@ import java.net.URI; -import org.apache.http.annotation.NotThreadSafe; - /** * HTTP POST method. *

@@ -54,7 +52,6 @@ * * @since 4.0 */ -@NotThreadSafe public class HttpPost extends HttpEntityEnclosingRequestBase { public final static String METHOD_NAME = "POST"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpPut.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpPut.java index ac0515a647..59c4ca2e47 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpPut.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpPut.java @@ -29,8 +29,6 @@ import java.net.URI; -import org.apache.http.annotation.NotThreadSafe; - /** * HTTP PUT method. *

@@ -46,7 +44,6 @@ * * @since 4.0 */ -@NotThreadSafe public class HttpPut extends HttpEntityEnclosingRequestBase { public final static String METHOD_NAME = "PUT"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestBase.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestBase.java index f997c3ca7d..e5c47d41ce 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestBase.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestBase.java @@ -31,7 +31,6 @@ import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.config.RequestConfig; import org.apache.http.message.BasicRequestLine; import org.apache.http.params.HttpProtocolParams; @@ -42,7 +41,6 @@ * @since 4.0 */ @SuppressWarnings("deprecation") -@NotThreadSafe public abstract class HttpRequestBase extends AbstractExecutionAwareRequest implements HttpUriRequest, Configurable { diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java index 3df8bbb5b6..dbfbd0e14d 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java @@ -36,7 +36,6 @@ import org.apache.http.HttpRequest; import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.message.AbstractHttpMessage; import org.apache.http.message.BasicRequestLine; import org.apache.http.params.HttpParams; @@ -50,7 +49,6 @@ * @since 4.3 */ @SuppressWarnings("deprecation") -@NotThreadSafe public class HttpRequestWrapper extends AbstractHttpMessage implements HttpUriRequest { private final HttpRequest original; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpTrace.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpTrace.java index c0bcc86165..51b373848b 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpTrace.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpTrace.java @@ -29,8 +29,6 @@ import java.net.URI; -import org.apache.http.annotation.NotThreadSafe; - /** * HTTP TRACE method. *

@@ -49,7 +47,6 @@ * * @since 4.0 */ -@NotThreadSafe public class HttpTrace extends HttpRequestBase { public final static String METHOD_NAME = "TRACE"; diff --git a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java index f6cd6816bc..b630dba945 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java @@ -43,7 +43,6 @@ import org.apache.http.HttpRequest; import org.apache.http.NameValuePair; import org.apache.http.ProtocolVersion; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.utils.URIBuilder; @@ -67,7 +66,6 @@ * * @since 4.3 */ -@NotThreadSafe public class RequestBuilder { private String method; diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java b/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java index db363c4921..e763e9a705 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java @@ -30,7 +30,6 @@ import java.net.URI; import java.util.List; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthSchemeProvider; import org.apache.http.auth.AuthState; import org.apache.http.client.AuthCache; @@ -54,7 +53,6 @@ * * @since 4.3 */ -@NotThreadSafe public class HttpClientContext extends HttpCoreContext { /** diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java index 9b260e2066..74749facff 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAcceptEncoding.java @@ -32,7 +32,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.config.RequestConfig; import org.apache.http.protocol.HttpContext; @@ -45,7 +46,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestAcceptEncoding implements HttpRequestInterceptor { private final String acceptEncoding; diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAddCookies.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAddCookies.java index b548d043ff..02656be6d4 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAddCookies.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAddCookies.java @@ -41,7 +41,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.CookieStore; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.RequestConfig; @@ -63,7 +64,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestAddCookies implements HttpRequestInterceptor { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java index fa6a362998..aa30073563 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java @@ -35,7 +35,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthProtocolState; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthScope; @@ -54,7 +55,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestAuthCache implements HttpRequestInterceptor { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestClientConnControl.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestClientConnControl.java index aba6602c9b..36049da41b 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestClientConnControl.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestClientConnControl.java @@ -34,7 +34,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.routing.RouteInfo; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; @@ -47,7 +48,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestClientConnControl implements HttpRequestInterceptor { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestDefaultHeaders.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestDefaultHeaders.java index 967270a1cf..1fd556ffe6 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestDefaultHeaders.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestDefaultHeaders.java @@ -34,7 +34,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.params.ClientPNames; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; @@ -45,7 +46,7 @@ * @since 4.0 */ @SuppressWarnings("deprecation") -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class RequestDefaultHeaders implements HttpRequestInterceptor { private final Collection defaultHeaders; diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestExpectContinue.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestExpectContinue.java index 27edc1784b..e958a7a44e 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestExpectContinue.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestExpectContinue.java @@ -36,7 +36,8 @@ import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.config.RequestConfig; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; @@ -52,7 +53,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RequestExpectContinue implements HttpRequestInterceptor { public RequestExpectContinue() { diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java index c4d0cfc9fe..8bb63c6572 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java @@ -37,7 +37,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.DecompressingEntity; import org.apache.http.client.entity.DeflateInputStream; @@ -55,7 +56,7 @@ * @since 4.1 * */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class ResponseContentEncoding implements HttpResponseInterceptor { public static final String UNCOMPRESSED = "http.client.response.uncompressed"; diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseProcessCookies.java b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseProcessCookies.java index 5f3cfaba0b..293721e0d4 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseProcessCookies.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseProcessCookies.java @@ -37,7 +37,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.CookieStore; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; @@ -53,7 +54,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class ResponseProcessCookies implements HttpResponseInterceptor { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java index 597dc2668c..be8e56d7cf 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java @@ -29,14 +29,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import org.apache.http.annotation.Immutable; - /** * A collection of utilities to workaround limitations of Java clone framework. * * @since 4.0 */ -@Immutable public class CloneUtils { /** diff --git a/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java index a18fbd7244..2de83fe2ed 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/DateUtils.java @@ -37,7 +37,6 @@ import java.util.Map; import java.util.TimeZone; -import org.apache.http.annotation.Immutable; import org.apache.http.util.Args; /** @@ -47,7 +46,6 @@ * * @since 4.3 */ -@Immutable public final class DateUtils { /** diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java index 227e494a15..1cc54ebce6 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java @@ -35,7 +35,6 @@ import org.apache.http.Consts; import org.apache.http.NameValuePair; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.util.InetAddressUtils; import org.apache.http.message.BasicNameValuePair; @@ -44,7 +43,6 @@ * * @since 4.2 */ -@NotThreadSafe public class URIBuilder { private String scheme; diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java index 72c299ef94..02f8c1ae93 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java @@ -33,7 +33,6 @@ import java.util.Stack; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; import org.apache.http.conn.routing.RouteInfo; import org.apache.http.util.Args; import org.apache.http.util.TextUtils; @@ -44,7 +43,6 @@ * * @since 4.0 */ -@Immutable public class URIUtils { /** diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index adc81c715b..8547cf0b4d 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -46,7 +46,6 @@ import org.apache.http.HeaderElement; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; -import org.apache.http.annotation.Immutable; import org.apache.http.entity.ContentType; import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.ParserCursor; @@ -60,7 +59,6 @@ * * @since 4.0 */ -@Immutable public class URLEncodedUtils { /** diff --git a/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java b/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java index a76bcdadb7..ed2b3297b5 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java +++ b/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java @@ -33,7 +33,6 @@ import java.util.Arrays; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; /** * A timeout while connecting to an HTTP server or waiting for an @@ -42,7 +41,6 @@ * * @since 4.0 */ -@Immutable public class ConnectTimeoutException extends InterruptedIOException { private static final long serialVersionUID = -4816682903149535989L; diff --git a/httpclient/src/main/java/org/apache/http/conn/ConnectionPoolTimeoutException.java b/httpclient/src/main/java/org/apache/http/conn/ConnectionPoolTimeoutException.java index 3328cc41e3..cd75078a7d 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ConnectionPoolTimeoutException.java +++ b/httpclient/src/main/java/org/apache/http/conn/ConnectionPoolTimeoutException.java @@ -27,8 +27,6 @@ package org.apache.http.conn; -import org.apache.http.annotation.Immutable; - /** * A timeout while waiting for an available connection * from a connection manager. @@ -36,7 +34,6 @@ * * @since 4.0 */ -@Immutable public class ConnectionPoolTimeoutException extends ConnectTimeoutException { private static final long serialVersionUID = -7898874842020245128L; diff --git a/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java b/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java index 50486311f1..fb7de2d6ba 100644 --- a/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java +++ b/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java @@ -29,7 +29,6 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.util.Args; /** @@ -43,7 +42,6 @@ */ // don't use FilterInputStream as the base class, we'd have to // override markSupported(), mark(), and reset() to disable them -@NotThreadSafe public class EofSensorInputStream extends InputStream implements ConnectionReleaseTrigger { /** diff --git a/httpclient/src/main/java/org/apache/http/conn/HttpHostConnectException.java b/httpclient/src/main/java/org/apache/http/conn/HttpHostConnectException.java index fa88a45cf8..7a0261664b 100644 --- a/httpclient/src/main/java/org/apache/http/conn/HttpHostConnectException.java +++ b/httpclient/src/main/java/org/apache/http/conn/HttpHostConnectException.java @@ -32,7 +32,6 @@ import java.util.Arrays; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; /** * A {@link ConnectException} that specifies the {@link HttpHost} that was @@ -40,7 +39,6 @@ * * @since 4.0 */ -@Immutable public class HttpHostConnectException extends ConnectException { private static final long serialVersionUID = -3194482710275220224L; diff --git a/httpclient/src/main/java/org/apache/http/conn/UnsupportedSchemeException.java b/httpclient/src/main/java/org/apache/http/conn/UnsupportedSchemeException.java index 268a0b80a0..69c66d96d1 100644 --- a/httpclient/src/main/java/org/apache/http/conn/UnsupportedSchemeException.java +++ b/httpclient/src/main/java/org/apache/http/conn/UnsupportedSchemeException.java @@ -29,14 +29,11 @@ import java.io.IOException; -import org.apache.http.annotation.Immutable; - /** * Signals failure to establish connection using an unknown protocol scheme. * * @since 4.3 */ -@Immutable public class UnsupportedSchemeException extends IOException { private static final long serialVersionUID = 3597127619218687636L; diff --git a/httpclient/src/main/java/org/apache/http/conn/routing/BasicRouteDirector.java b/httpclient/src/main/java/org/apache/http/conn/routing/BasicRouteDirector.java index eff3f04a2a..09764b4744 100644 --- a/httpclient/src/main/java/org/apache/http/conn/routing/BasicRouteDirector.java +++ b/httpclient/src/main/java/org/apache/http/conn/routing/BasicRouteDirector.java @@ -27,7 +27,8 @@ package org.apache.http.conn.routing; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; /** @@ -35,7 +36,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicRouteDirector implements HttpRouteDirector { /** diff --git a/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java b/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java index 847fa7e8f9..60a02e7265 100644 --- a/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java +++ b/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java @@ -35,7 +35,8 @@ import java.util.List; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.LangUtils; @@ -44,7 +45,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class HttpRoute implements RouteInfo, Cloneable { /** The target host to connect to. */ diff --git a/httpclient/src/main/java/org/apache/http/conn/routing/RouteTracker.java b/httpclient/src/main/java/org/apache/http/conn/routing/RouteTracker.java index e55079970e..b58aca67d3 100644 --- a/httpclient/src/main/java/org/apache/http/conn/routing/RouteTracker.java +++ b/httpclient/src/main/java/org/apache/http/conn/routing/RouteTracker.java @@ -30,7 +30,6 @@ import java.net.InetAddress; import org.apache.http.HttpHost; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.util.Args; import org.apache.http.util.Asserts; import org.apache.http.util.LangUtils; @@ -40,7 +39,6 @@ * * @since 4.0 */ -@NotThreadSafe public final class RouteTracker implements RouteInfo, Cloneable { /** The target host to connect to. */ diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java b/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java index 68d7aa98e7..6d02b95fe4 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java @@ -28,7 +28,8 @@ import java.util.Locale; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.LangUtils; @@ -50,7 +51,7 @@ * @deprecated (4.3) use {@link org.apache.http.conn.SchemePortResolver} for default port * resolution and {@link org.apache.http.config.Registry} for socket factory lookups. */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public final class Scheme { diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeRegistry.java b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeRegistry.java index 6928ce5629..d05f232e81 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeRegistry.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeRegistry.java @@ -32,7 +32,8 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpHost; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; /** @@ -43,7 +44,7 @@ * * @deprecated (4.3) use {@link org.apache.http.config.Registry} */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public final class SchemeRegistry { diff --git a/httpclient/src/main/java/org/apache/http/conn/socket/PlainConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/socket/PlainConnectionSocketFactory.java index 193e73da08..3ec167c668 100644 --- a/httpclient/src/main/java/org/apache/http/conn/socket/PlainConnectionSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/socket/PlainConnectionSocketFactory.java @@ -32,7 +32,8 @@ import java.net.Socket; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.protocol.HttpContext; /** @@ -40,7 +41,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class PlainConnectionSocketFactory implements ConnectionSocketFactory { public static final PlainConnectionSocketFactory INSTANCE = new PlainConnectionSocketFactory(); diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java index 3dc856ed7c..29d7763563 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java @@ -27,7 +27,8 @@ package org.apache.http.conn.ssl; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * The ALLOW_ALL HostnameVerifier essentially turns hostname verification @@ -39,7 +40,7 @@ * @deprecated (4.4) Use {@link org.apache.http.conn.ssl.NoopHostnameVerifier} */ @Deprecated -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class AllowAllHostnameVerifier extends AbstractVerifier { public static final AllowAllHostnameVerifier INSTANCE = new AllowAllHostnameVerifier(); diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java index 4c4aee9a0e..9fd886745c 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java @@ -29,7 +29,8 @@ import javax.net.ssl.SSLException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * The HostnameVerifier that works the same way as Curl and Firefox. @@ -47,7 +48,7 @@ * * @deprecated (4.4) Use {@link org.apache.http.conn.ssl.DefaultHostnameVerifier} */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class BrowserCompatHostnameVerifier extends AbstractVerifier { diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 299e7a7664..64b63f731e 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -51,7 +51,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.DomainType; import org.apache.http.conn.util.InetAddressUtils; import org.apache.http.conn.util.PublicSuffixMatcher; @@ -61,7 +62,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public final class DefaultHostnameVerifier implements HostnameVerifier { enum TYPE { IPv4, IPv6, DNS } diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/NoopHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/NoopHostnameVerifier.java index 1b5cdd9545..40ceb8a25d 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/NoopHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/NoopHostnameVerifier.java @@ -30,7 +30,8 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSession; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * The NO_OP HostnameVerifier essentially turns hostname verification @@ -38,7 +39,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NoopHostnameVerifier implements HostnameVerifier { public static final NoopHostnameVerifier INSTANCE = new NoopHostnameVerifier(); diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java index df8689b420..504f24adab 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java @@ -50,7 +50,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.util.PublicSuffixMatcherLoader; import org.apache.http.protocol.HttpContext; @@ -133,7 +134,8 @@ * * @since 4.3 */ -@ThreadSafe @SuppressWarnings("deprecation") +@Contract(threading = ThreadingBehavior.SAFE) +@SuppressWarnings("deprecation") public class SSLConnectionSocketFactory implements LayeredConnectionSocketFactory { public static final String TLS = "TLS"; diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java index 362d6abe91..eb1c05750d 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java @@ -29,7 +29,8 @@ import javax.net.ssl.SSLException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * The Strict HostnameVerifier works the same way as Sun Java 1.4, Sun @@ -53,7 +54,7 @@ * * @deprecated (4.4) Use {@link org.apache.http.conn.ssl.DefaultHostnameVerifier} */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @Deprecated public class StrictHostnameVerifier extends AbstractVerifier { diff --git a/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java b/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java index acee8afa23..8715200aa5 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java @@ -29,14 +29,11 @@ import java.util.regex.Pattern; -import org.apache.http.annotation.Immutable; - /** * A collection of utilities relating to InetAddresses. * * @since 4.0 */ -@Immutable public class InetAddressUtils { private InetAddressUtils() { diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixList.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixList.java index dfdd928ce5..273c5ca325 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixList.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixList.java @@ -29,7 +29,8 @@ import java.util.Collections; import java.util.List; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; /** @@ -41,7 +42,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class PublicSuffixList { private final DomainType type; diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixListParser.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixListParser.java index 0bf63e18ee..d13210fa28 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixListParser.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixListParser.java @@ -32,7 +32,8 @@ import java.util.ArrayList; import java.util.List; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * Parses the list from publicsuffix.org @@ -40,7 +41,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class PublicSuffixListParser { public PublicSuffixListParser() { diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java index 2ec340f613..ce2a2c901f 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java @@ -33,7 +33,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; /** @@ -46,7 +47,7 @@ * * @since 4.4 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public final class PublicSuffixMatcher { private final Map rules; diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java index 5a25b4610c..8783c5b96e 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcherLoader.java @@ -38,7 +38,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.Consts; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; /** @@ -46,7 +47,7 @@ * * @since 4.4 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public final class PublicSuffixMatcherLoader { private static PublicSuffixMatcher load(final InputStream in) throws IOException { diff --git a/httpclient/src/main/java/org/apache/http/cookie/CookieIdentityComparator.java b/httpclient/src/main/java/org/apache/http/cookie/CookieIdentityComparator.java index 935a5a3389..d5a11e1299 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/CookieIdentityComparator.java +++ b/httpclient/src/main/java/org/apache/http/cookie/CookieIdentityComparator.java @@ -30,7 +30,8 @@ import java.io.Serializable; import java.util.Comparator; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * This cookie comparator can be used to compare identity of cookies. @@ -40,7 +41,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class CookieIdentityComparator implements Serializable, Comparator { private static final long serialVersionUID = 4466565437490631532L; diff --git a/httpclient/src/main/java/org/apache/http/cookie/CookieOrigin.java b/httpclient/src/main/java/org/apache/http/cookie/CookieOrigin.java index b46f6bd35a..d856258f3d 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/CookieOrigin.java +++ b/httpclient/src/main/java/org/apache/http/cookie/CookieOrigin.java @@ -28,7 +28,8 @@ import java.util.Locale; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; import org.apache.http.util.TextUtils; @@ -38,7 +39,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public final class CookieOrigin { private final String host; diff --git a/httpclient/src/main/java/org/apache/http/cookie/CookiePathComparator.java b/httpclient/src/main/java/org/apache/http/cookie/CookiePathComparator.java index f9e3e7672d..c8fe21cd60 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/CookiePathComparator.java +++ b/httpclient/src/main/java/org/apache/http/cookie/CookiePathComparator.java @@ -30,7 +30,8 @@ import java.io.Serializable; import java.util.Comparator; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * This cookie comparator ensures that multiple cookies satisfying @@ -47,7 +48,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class CookiePathComparator implements Serializable, Comparator { public static final CookiePathComparator INSTANCE = new CookiePathComparator(); diff --git a/httpclient/src/main/java/org/apache/http/cookie/CookiePriorityComparator.java b/httpclient/src/main/java/org/apache/http/cookie/CookiePriorityComparator.java index 77e4e01321..ab0932df50 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/CookiePriorityComparator.java +++ b/httpclient/src/main/java/org/apache/http/cookie/CookiePriorityComparator.java @@ -30,7 +30,8 @@ import java.util.Comparator; import java.util.Date; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.impl.cookie.BasicClientCookie; /** @@ -40,7 +41,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class CookiePriorityComparator implements Comparator { public static final CookiePriorityComparator INSTANCE = new CookiePriorityComparator(); diff --git a/httpclient/src/main/java/org/apache/http/cookie/CookieRestrictionViolationException.java b/httpclient/src/main/java/org/apache/http/cookie/CookieRestrictionViolationException.java index 3b30a977b5..b1a482e89a 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/CookieRestrictionViolationException.java +++ b/httpclient/src/main/java/org/apache/http/cookie/CookieRestrictionViolationException.java @@ -27,15 +27,12 @@ package org.apache.http.cookie; -import org.apache.http.annotation.Immutable; - /** * Signals that a cookie violates a restriction imposed by the cookie * specification. * * @since 4.1 */ -@Immutable public class CookieRestrictionViolationException extends MalformedCookieException { private static final long serialVersionUID = 7371235577078589013L; diff --git a/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java b/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java index 43e6ffeb65..e24be611f3 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java +++ b/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java @@ -34,7 +34,8 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpRequest; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.config.Lookup; import org.apache.http.params.HttpParams; import org.apache.http.protocol.ExecutionContext; @@ -50,7 +51,7 @@ * * @deprecated (4.3) use {@link org.apache.http.config.Registry}. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) @Deprecated public final class CookieSpecRegistry implements Lookup { diff --git a/httpclient/src/main/java/org/apache/http/cookie/MalformedCookieException.java b/httpclient/src/main/java/org/apache/http/cookie/MalformedCookieException.java index da70979c62..4c881a9134 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/MalformedCookieException.java +++ b/httpclient/src/main/java/org/apache/http/cookie/MalformedCookieException.java @@ -28,7 +28,6 @@ package org.apache.http.cookie; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; /** * Signals that a cookie is in some way invalid or illegal in a given @@ -37,7 +36,6 @@ * * @since 4.0 */ -@Immutable public class MalformedCookieException extends ProtocolException { private static final long serialVersionUID = -6695462944287282185L; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java index 452516a881..296b15c34e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java @@ -31,7 +31,6 @@ import org.apache.http.FormattedHeader; import org.apache.http.Header; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.ChallengeState; @@ -53,7 +52,6 @@ * * @since 4.0 */ -@NotThreadSafe public abstract class AuthSchemeBase implements ContextAwareAuthScheme { protected ChallengeState challengeState; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java index 2f51de7036..cfd5a6e055 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java @@ -32,7 +32,6 @@ import org.apache.http.Consts; import org.apache.http.Header; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.ChallengeState; @@ -50,7 +49,6 @@ * * @since 4.0 */ -@NotThreadSafe public class BasicScheme extends RFC2617Scheme { private static final long serialVersionUID = -1931571557597830536L; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/BasicSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/BasicSchemeFactory.java index 5409a771f1..69402d2410 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/BasicSchemeFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/BasicSchemeFactory.java @@ -29,7 +29,8 @@ import java.nio.charset.Charset; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeFactory; import org.apache.http.auth.AuthSchemeProvider; @@ -42,7 +43,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @SuppressWarnings("deprecation") public class BasicSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java index a7607e330a..1e3c62f415 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java @@ -43,7 +43,6 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.ChallengeState; @@ -72,7 +71,6 @@ * * @since 4.0 */ -@NotThreadSafe public class DigestScheme extends RFC2617Scheme { private static final long serialVersionUID = 3883908186234566916L; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DigestSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/DigestSchemeFactory.java index 67a4e9edb8..3cc9796132 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/DigestSchemeFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/DigestSchemeFactory.java @@ -29,7 +29,8 @@ import java.nio.charset.Charset; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeFactory; import org.apache.http.auth.AuthSchemeProvider; @@ -42,7 +43,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @SuppressWarnings("deprecation") public class DigestSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java index d9e008f402..1fbc86a14e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java @@ -35,7 +35,6 @@ import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.Credentials; @@ -58,7 +57,6 @@ /** * @since 4.2 */ -@NotThreadSafe public abstract class GGSSchemeBase extends AuthSchemeBase { enum State { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/KerberosScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/KerberosScheme.java index 9b2ba6206e..6cbb05bb9d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/KerberosScheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/KerberosScheme.java @@ -28,7 +28,6 @@ import org.apache.http.Header; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.Credentials; import org.apache.http.protocol.HttpContext; @@ -41,7 +40,6 @@ * * @since 4.2 */ -@NotThreadSafe public class KerberosScheme extends GGSSchemeBase { private static final String KERBEROS_OID = "1.2.840.113554.1.2.2"; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/KerberosSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/KerberosSchemeFactory.java index 431258e963..7096e69824 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/KerberosSchemeFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/KerberosSchemeFactory.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.auth; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeFactory; import org.apache.http.auth.AuthSchemeProvider; @@ -39,7 +40,7 @@ * * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @SuppressWarnings("deprecation") public class KerberosSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java index f902ae1bc8..04180c0df1 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java @@ -26,7 +26,6 @@ */ package org.apache.http.impl.auth; -import org.apache.http.annotation.Immutable; import org.apache.http.auth.AuthenticationException; /** @@ -35,7 +34,6 @@ * * @since 4.0 */ -@Immutable public class NTLMEngineException extends AuthenticationException { private static final long serialVersionUID = 6027981323731768824L; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 890f6474c9..1a7dc8b575 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -38,7 +38,6 @@ import org.apache.commons.codec.binary.Base64; import org.apache.http.Consts; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.util.CharsetUtils; import org.apache.http.util.EncodingUtils; @@ -48,7 +47,6 @@ * * @since 4.1 */ -@NotThreadSafe final class NTLMEngineImpl implements NTLMEngine { /** Unicode encoding */ diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMScheme.java index 1ec4957d4a..cd1a2127fb 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMScheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMScheme.java @@ -28,7 +28,6 @@ import org.apache.http.Header; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.Credentials; @@ -45,7 +44,6 @@ * * @since 4.0 */ -@NotThreadSafe public class NTLMScheme extends AuthSchemeBase { enum State { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMSchemeFactory.java index 8e38c82ae2..869f6667eb 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMSchemeFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMSchemeFactory.java @@ -27,7 +27,8 @@ package org.apache.http.impl.auth; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeFactory; import org.apache.http.auth.AuthSchemeProvider; @@ -41,7 +42,7 @@ * * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @SuppressWarnings("deprecation") public class NTLMSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/RFC2617Scheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/RFC2617Scheme.java index 9475c03a40..d7b6852d25 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/RFC2617Scheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/RFC2617Scheme.java @@ -39,7 +39,6 @@ import org.apache.http.Consts; import org.apache.http.HeaderElement; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.ChallengeState; import org.apache.http.auth.MalformedChallengeException; import org.apache.http.auth.params.AuthPNames; @@ -57,7 +56,6 @@ * @since 4.0 */ @SuppressWarnings("deprecation") -@NotThreadSafe // AuthSchemeBase, params public abstract class RFC2617Scheme extends AuthSchemeBase implements Serializable { private static final long serialVersionUID = -2845454858205884623L; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoScheme.java index 808738b442..46ebeb8628 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoScheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoScheme.java @@ -28,7 +28,6 @@ import org.apache.http.Header; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.Credentials; import org.apache.http.protocol.HttpContext; @@ -42,7 +41,6 @@ * * @since 4.2 */ -@NotThreadSafe public class SPNegoScheme extends GGSSchemeBase { private static final String SPNEGO_OID = "1.3.6.1.5.5.2"; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoSchemeFactory.java index 42e506dfd1..fa09a2b585 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoSchemeFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/SPNegoSchemeFactory.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.auth; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeFactory; import org.apache.http.auth.AuthSchemeProvider; @@ -39,7 +40,7 @@ * * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) @SuppressWarnings("deprecation") public class SPNegoSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider { diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java b/httpclient/src/main/java/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java index 2d6b6ec84d..0465af5158 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java @@ -26,8 +26,6 @@ */ package org.apache.http.impl.auth; -import org.apache.http.annotation.Immutable; - /** * Authentication credentials required to respond to a authentication * challenge are invalid @@ -35,7 +33,6 @@ * * @since 4.0 */ -@Immutable public class UnsupportedDigestAlgorithmException extends RuntimeException { private static final long serialVersionUID = 319558534317118022L; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AbstractResponseHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/AbstractResponseHandler.java index 290a88ce37..d87775bddd 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AbstractResponseHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AbstractResponseHandler.java @@ -32,7 +32,8 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.util.EntityUtils; @@ -50,7 +51,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public abstract class AbstractResponseHandler implements ResponseHandler { /** diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java index cd15aeabb9..57df6141f2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java @@ -43,7 +43,8 @@ import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthOption; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthSchemeProvider; @@ -62,7 +63,7 @@ import org.apache.http.util.Args; import org.apache.http.util.CharArrayBuffer; -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) abstract class AuthenticationStrategyImpl implements AuthenticationStrategy { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java index 97dabb3d73..4d163bae53 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java @@ -38,7 +38,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.client.AuthCache; import org.apache.http.conn.SchemePortResolver; @@ -56,7 +57,7 @@ * * @since 4.1 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class BasicAuthCache implements AuthCache { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java index 52b76b1cb8..d2468f6330 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java @@ -33,8 +33,8 @@ import java.util.List; import java.util.TreeSet; -import org.apache.http.annotation.GuardedBy; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.CookieStore; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieIdentityComparator; @@ -45,12 +45,11 @@ * * @since 4.0 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class BasicCookieStore implements CookieStore, Serializable { private static final long serialVersionUID = -7581093305228232025L; - @GuardedBy("this") private final TreeSet cookies; public BasicCookieStore() { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicCredentialsProvider.java index 352bbfd54f..99bab9131e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicCredentialsProvider.java @@ -29,7 +29,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.client.CredentialsProvider; @@ -40,7 +41,7 @@ * * @since 4.0 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class BasicCredentialsProvider implements CredentialsProvider { private final ConcurrentHashMap credMap; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicResponseHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicResponseHandler.java index 76766ea7e4..09fdb52529 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicResponseHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicResponseHandler.java @@ -31,7 +31,8 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.HttpResponseException; import org.apache.http.util.EntityUtils; @@ -48,7 +49,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicResponseHandler extends AbstractResponseHandler { /** diff --git a/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java index 16dfae215c..866d6c12a2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/CloseableHttpClient.java @@ -36,7 +36,8 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; @@ -52,7 +53,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public abstract class CloseableHttpClient implements HttpClient, Closeable { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultConnectionKeepAliveStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultConnectionKeepAliveStrategy.java index 6e757d1ee0..d162db7650 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultConnectionKeepAliveStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultConnectionKeepAliveStrategy.java @@ -29,7 +29,8 @@ import org.apache.http.HeaderElement; import org.apache.http.HeaderElementIterator; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.message.BasicHeaderElementIterator; import org.apache.http.protocol.HTTP; @@ -45,7 +46,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy { public static final DefaultConnectionKeepAliveStrategy INSTANCE = new DefaultConnectionKeepAliveStrategy(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java index b647cd3437..dd5eb4a850 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java @@ -40,7 +40,8 @@ import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.protocol.HttpClientContext; @@ -52,7 +53,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultHttpRequestRetryHandler implements HttpRequestRetryHandler { public static final DefaultHttpRequestRetryHandler INSTANCE = new DefaultHttpRequestRetryHandler(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java index 47249ee5fb..0e02b2989a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java @@ -39,7 +39,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.CircularRedirectException; import org.apache.http.client.RedirectStrategy; import org.apache.http.client.config.RequestConfig; @@ -70,7 +71,7 @@ * @see LaxRedirectStrategy * @since 4.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultRedirectStrategy implements RedirectStrategy { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java index f007207070..e80bc5b53c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java @@ -29,7 +29,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.ServiceUnavailableRetryStrategy; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; @@ -41,7 +42,7 @@ * * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultServiceUnavailableRetryStrategy implements ServiceUnavailableRetryStrategy { /** diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java index e2a43c4b81..a47f027bd7 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultUserTokenHandler.java @@ -31,7 +31,8 @@ import javax.net.ssl.SSLSession; import org.apache.http.HttpConnection; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthState; import org.apache.http.auth.Credentials; @@ -54,7 +55,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultUserTokenHandler implements UserTokenHandler { public static final DefaultUserTokenHandler INSTANCE = new DefaultUserTokenHandler(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java b/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java index 15aedd564d..061ae3f5c8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java @@ -35,7 +35,6 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.ProtocolException; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.protocol.HTTP; @@ -53,7 +52,6 @@ * @deprecated (4.3) do not use. */ @Deprecated -@NotThreadSafe // e.g. [gs]etEntity() public class EntityEnclosingRequestWrapper extends RequestWrapper implements HttpEntityEnclosingRequest { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/FutureRequestExecutionService.java b/httpclient/src/main/java/org/apache/http/impl/client/FutureRequestExecutionService.java index 0fcfd4dfc0..89b06d499d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/FutureRequestExecutionService.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/FutureRequestExecutionService.java @@ -31,7 +31,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpUriRequest; @@ -42,7 +43,7 @@ * HttpAsyncClientWithFuture wraps calls to execute with a {@link HttpRequestFutureTask} * and schedules them using the provided executor service. Scheduled calls may be cancelled. */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class FutureRequestExecutionService implements Closeable { private final HttpClient httpclient; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index dab3ab1353..507f7d390d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -47,7 +47,6 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponseInterceptor; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthSchemeProvider; import org.apache.http.client.AuthenticationStrategy; import org.apache.http.client.BackoffManager; @@ -153,7 +152,6 @@ * * @since 4.3 */ -@NotThreadSafe public class HttpClientBuilder { private HttpRequestExecutor requestExec; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java index 569b047a64..c43b460ac5 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java @@ -27,7 +27,6 @@ package org.apache.http.impl.client; -import org.apache.http.annotation.Immutable; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; @@ -35,7 +34,6 @@ * Factory methods for {@link CloseableHttpClient} instances. * @since 4.3 */ -@Immutable public class HttpClients { private HttpClients() { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java index d49dfee7f8..20bf060529 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java @@ -37,7 +37,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthSchemeProvider; import org.apache.http.auth.AuthState; import org.apache.http.client.ClientProtocolException; @@ -72,7 +73,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) @SuppressWarnings("deprecation") class InternalHttpClient extends CloseableHttpClient implements Configurable { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java index 8e7ba7e24d..fed513ac66 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/LaxRedirectStrategy.java @@ -27,7 +27,8 @@ package org.apache.http.impl.client; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; @@ -41,7 +42,7 @@ * * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class LaxRedirectStrategy extends DefaultRedirectStrategy { public static final LaxRedirectStrategy INSTANCE = new LaxRedirectStrategy(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java index 6d1ead7ec6..30ce492717 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java @@ -33,7 +33,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -61,7 +62,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) @SuppressWarnings("deprecation") class MinimalHttpClient extends CloseableHttpClient { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/NoopUserTokenHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/NoopUserTokenHandler.java index 9d21a6b86d..3ab1799c5f 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/NoopUserTokenHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/NoopUserTokenHandler.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.client; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.UserTokenHandler; import org.apache.http.protocol.HttpContext; @@ -35,7 +36,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NoopUserTokenHandler implements UserTokenHandler { public static final NoopUserTokenHandler INSTANCE = new NoopUserTokenHandler(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/ProxyAuthenticationStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/ProxyAuthenticationStrategy.java index 49e6e91222..2dba232b07 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/ProxyAuthenticationStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/ProxyAuthenticationStrategy.java @@ -30,7 +30,8 @@ import java.util.Collection; import org.apache.http.HttpStatus; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AUTH; import org.apache.http.client.config.RequestConfig; @@ -40,7 +41,7 @@ * * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class ProxyAuthenticationStrategy extends AuthenticationStrategyImpl { public static final ProxyAuthenticationStrategy INSTANCE = new ProxyAuthenticationStrategy(); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/RedirectLocations.java b/httpclient/src/main/java/org/apache/http/impl/client/RedirectLocations.java index e0d44648e1..e583b52b7e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/RedirectLocations.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/RedirectLocations.java @@ -35,15 +35,12 @@ import java.util.List; import java.util.Set; -import org.apache.http.annotation.NotThreadSafe; - /** * This class represents a collection of {@link java.net.URI}s used * as redirect locations. * * @since 4.0 */ -@NotThreadSafe // HashSet/ArrayList are not synch. public class RedirectLocations extends AbstractList { private final Set unique; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/RequestWrapper.java b/httpclient/src/main/java/org/apache/http/impl/client/RequestWrapper.java index be6a743ab5..61eb5d1e4f 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/RequestWrapper.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/RequestWrapper.java @@ -34,7 +34,6 @@ import org.apache.http.ProtocolException; import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.AbstractHttpMessage; import org.apache.http.message.BasicRequestLine; @@ -54,7 +53,6 @@ * * @deprecated (4.3) do not use. */ -@NotThreadSafe @Deprecated public class RequestWrapper extends AbstractHttpMessage implements HttpUriRequest { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/StandardHttpRequestRetryHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/StandardHttpRequestRetryHandler.java index ae3342bf58..0680c133d7 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/StandardHttpRequestRetryHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/StandardHttpRequestRetryHandler.java @@ -32,7 +32,8 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; /** * {@link org.apache.http.client.HttpRequestRetryHandler} which assumes @@ -45,7 +46,7 @@ * * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class StandardHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler { private final Map idempotentMethods; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index 8a160d914d..f6f30ccfeb 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -33,7 +33,8 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpHost; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.auth.NTCredentials; @@ -48,7 +49,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class SystemDefaultCredentialsProvider implements CredentialsProvider { private static final Map SCHEME_MAP; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/TargetAuthenticationStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/TargetAuthenticationStrategy.java index dad2eb712f..5737d745ce 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/TargetAuthenticationStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/TargetAuthenticationStrategy.java @@ -30,7 +30,8 @@ import java.util.Collection; import org.apache.http.HttpStatus; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AUTH; import org.apache.http.client.config.RequestConfig; @@ -40,7 +41,7 @@ * * @since 4.2 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class TargetAuthenticationStrategy extends AuthenticationStrategyImpl { public static final TargetAuthenticationStrategy INSTANCE = new TargetAuthenticationStrategy(); diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java index 92ca644617..08153cdd12 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java @@ -38,8 +38,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.HttpClientConnection; import org.apache.http.HttpHost; -import org.apache.http.annotation.GuardedBy; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.config.ConnectionConfig; import org.apache.http.config.Lookup; import org.apache.http.config.Registry; @@ -50,8 +50,8 @@ import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.HttpClientConnectionOperator; import org.apache.http.conn.HttpConnectionFactory; -import org.apache.http.conn.SchemePortResolver; import org.apache.http.conn.ManagedHttpClientConnection; +import org.apache.http.conn.SchemePortResolver; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; @@ -79,7 +79,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class BasicHttpClientConnectionManager implements HttpClientConnectionManager, Closeable { private final Log log = LogFactory.getLog(getClass()); @@ -87,28 +87,13 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan private final HttpClientConnectionOperator connectionOperator; private final HttpConnectionFactory connFactory; - @GuardedBy("this") private ManagedHttpClientConnection conn; - - @GuardedBy("this") private HttpRoute route; - - @GuardedBy("this") private Object state; - - @GuardedBy("this") private long updated; - - @GuardedBy("this") private long expiry; - - @GuardedBy("this") private boolean leased; - - @GuardedBy("this") private SocketConfig socketConfig; - - @GuardedBy("this") private ConnectionConfig connConfig; private final AtomicBoolean isShutdown; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java b/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java index f9cc0d6a62..eee9b78d7b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java @@ -31,7 +31,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ManagedHttpClientConnection; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.pool.AbstractConnPool; @@ -41,7 +42,7 @@ /** * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) class CPool extends AbstractConnPool { private static final AtomicLong COUNTER = new AtomicLong(); diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java index 71f9183933..cb89d27c74 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java @@ -32,7 +32,8 @@ import org.apache.commons.logging.Log; import org.apache.http.HttpClientConnection; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.ManagedHttpClientConnection; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.pool.PoolEntry; @@ -40,7 +41,7 @@ /** * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) class CPoolEntry extends PoolEntry { private final Log log; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java index 27b7f87668..8c8f623da8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java @@ -38,14 +38,12 @@ import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.ManagedHttpClientConnection; import org.apache.http.protocol.HttpContext; /** * @since 4.3 */ -@NotThreadSafe class CPoolProxy implements ManagedHttpClientConnection, HttpContext { private volatile CPoolEntry poolEntry; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/ConnectionShutdownException.java b/httpclient/src/main/java/org/apache/http/impl/conn/ConnectionShutdownException.java index b0b6bb6ae8..1737fbb6bc 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/ConnectionShutdownException.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/ConnectionShutdownException.java @@ -27,15 +27,12 @@ package org.apache.http.impl.conn; -import org.apache.http.annotation.Immutable; - /** * Signals that the connection has been shut down or released back to the * the connection pool * * @since 4.1 */ -@Immutable public class ConnectionShutdownException extends IllegalStateException { private static final long serialVersionUID = 5868657401162844497L; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java index 582136408e..76af8e81b8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java @@ -37,7 +37,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Lookup; import org.apache.http.config.SocketConfig; @@ -60,7 +61,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class DefaultHttpClientConnectionOperator implements HttpClientConnectionOperator { static final String SOCKET_FACTORY_REGISTRY = "http.socket-factory-registry"; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParser.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParser.java index c685bf276d..e5578ecfe6 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParser.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParser.java @@ -37,7 +37,6 @@ import org.apache.http.NoHttpResponseException; import org.apache.http.ProtocolException; import org.apache.http.StatusLine; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.config.MessageConstraints; import org.apache.http.impl.DefaultHttpResponseFactory; import org.apache.http.impl.io.AbstractMessageParser; @@ -55,7 +54,6 @@ * @since 4.2 */ @SuppressWarnings("deprecation") -@NotThreadSafe public class DefaultHttpResponseParser extends AbstractMessageParser { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java index f5c0af01f5..93d2819068 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java @@ -29,7 +29,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpResponseFactory; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.config.MessageConstraints; import org.apache.http.impl.DefaultHttpResponseFactory; import org.apache.http.io.HttpMessageParser; @@ -43,7 +44,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class DefaultHttpResponseParserFactory implements HttpMessageParserFactory { public static final DefaultHttpResponseParserFactory INSTANCE = new DefaultHttpResponseParserFactory(); diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java index 7eabfac652..1a74f5ea95 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java @@ -40,7 +40,6 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.config.MessageConstraints; import org.apache.http.conn.ManagedHttpClientConnection; import org.apache.http.entity.ContentLengthStrategy; @@ -53,7 +52,6 @@ * Default {@link ManagedHttpClientConnection} implementation. * @since 4.3 */ -@NotThreadSafe public class DefaultManagedHttpClientConnection extends DefaultBHttpClientConnection implements ManagedHttpClientConnection, HttpContext { diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultProxyRoutePlanner.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultProxyRoutePlanner.java index 376654a060..12a67d725c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultProxyRoutePlanner.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultProxyRoutePlanner.java @@ -30,7 +30,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.SchemePortResolver; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; @@ -41,7 +42,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class DefaultProxyRoutePlanner extends DefaultRoutePlanner { private final HttpHost proxy; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java index b56d2f8ed7..3652115c1d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java @@ -33,7 +33,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.conn.SchemePortResolver; @@ -49,7 +50,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class DefaultRoutePlanner implements HttpRoutePlanner { private final SchemePortResolver schemePortResolver; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultSchemePortResolver.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultSchemePortResolver.java index c5d54ed9f7..aaff79c58b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultSchemePortResolver.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultSchemePortResolver.java @@ -27,7 +27,8 @@ package org.apache.http.impl.conn; import org.apache.http.HttpHost; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.SchemePortResolver; import org.apache.http.conn.UnsupportedSchemeException; import org.apache.http.util.Args; @@ -37,7 +38,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultSchemePortResolver implements SchemePortResolver { public static final DefaultSchemePortResolver INSTANCE = new DefaultSchemePortResolver(); diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java index c47e7c0859..90b2435e79 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingInputStream.java @@ -27,8 +27,6 @@ package org.apache.http.impl.conn; -import org.apache.http.annotation.NotThreadSafe; - import java.io.IOException; import java.io.InputStream; @@ -37,7 +35,6 @@ * * @since 4.3 */ -@NotThreadSafe class LoggingInputStream extends InputStream { private final InputStream in; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java index 2614b0c9bb..6d3b34fe6a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java @@ -27,24 +27,22 @@ package org.apache.http.impl.conn; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; + import org.apache.commons.logging.Log; import org.apache.http.Header; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.config.MessageConstraints; import org.apache.http.entity.ContentLengthStrategy; import org.apache.http.io.HttpMessageParserFactory; import org.apache.http.io.HttpMessageWriterFactory; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; - -@NotThreadSafe class LoggingManagedHttpClientConnection extends DefaultManagedHttpClientConnection { private final Log log; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java index b292453f4e..3b084c12df 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingOutputStream.java @@ -27,8 +27,6 @@ package org.apache.http.impl.conn; -import org.apache.http.annotation.NotThreadSafe; - import java.io.IOException; import java.io.OutputStream; @@ -37,7 +35,6 @@ * * @since 4.3 */ -@NotThreadSafe class LoggingOutputStream extends OutputStream { private final OutputStream out; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java b/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java index 2d7d521dc3..7057c3e3fe 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java @@ -37,7 +37,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.config.ConnectionConfig; import org.apache.http.conn.HttpConnectionFactory; import org.apache.http.conn.ManagedHttpClientConnection; @@ -53,7 +54,7 @@ * Factory for {@link ManagedHttpClientConnection} instances. * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class ManagedHttpClientConnectionFactory implements HttpConnectionFactory { diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java index 0389a43d93..81928acb56 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java @@ -42,7 +42,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.HttpClientConnection; import org.apache.http.HttpHost; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.config.ConnectionConfig; import org.apache.http.config.Lookup; import org.apache.http.config.Registry; @@ -99,7 +100,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public class PoolingHttpClientConnectionManager implements HttpClientConnectionManager, ConnPoolControl, Closeable { diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java b/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java index 30de52c193..b4cac8b714 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java @@ -37,7 +37,8 @@ import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.SchemePortResolver; import org.apache.http.protocol.HttpContext; @@ -49,7 +50,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class SystemDefaultRoutePlanner extends DefaultRoutePlanner { private final ProxySelector proxySelector; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java b/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java index e3bffd33f7..48195e5f0c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java @@ -31,7 +31,8 @@ import java.io.InputStream; import org.apache.commons.logging.Log; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.util.Args; /** @@ -40,7 +41,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class Wire { private final Log log; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieAttributeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieAttributeHandler.java index ccf12dd5bf..80408a9f4e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieAttributeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieAttributeHandler.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieAttributeHandler; import org.apache.http.cookie.CookieOrigin; @@ -36,7 +37,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public abstract class AbstractCookieAttributeHandler implements CookieAttributeHandler { @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java index 1c6914a6ec..c0c7c5b9f8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/AbstractCookieSpec.java @@ -32,7 +32,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.CookieAttributeHandler; import org.apache.http.cookie.CookieSpec; @@ -47,7 +48,7 @@ * * @since 4.0 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public abstract class AbstractCookieSpec implements CookieSpec { /** diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie.java index dc261ab59b..e5503bc914 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie.java @@ -33,7 +33,6 @@ import java.util.Locale; import java.util.Map; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.SetCookie; import org.apache.http.util.Args; @@ -43,7 +42,6 @@ * * @since 4.0 */ -@NotThreadSafe public class BasicClientCookie implements SetCookie, ClientCookie, Cloneable, Serializable { private static final long serialVersionUID = -3869795591041535538L; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie2.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie2.java index e9c50a3020..9a191ffe8a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie2.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicClientCookie2.java @@ -29,7 +29,6 @@ import java.util.Date; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.cookie.SetCookie2; /** @@ -37,7 +36,6 @@ * * @since 4.0 */ -@NotThreadSafe public class BasicClientCookie2 extends BasicClientCookie implements SetCookie2 { private static final long serialVersionUID = -7744598295706617057L; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicCommentHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicCommentHandler.java index 14c9cfe594..3bd7794f67 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicCommentHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicCommentHandler.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.MalformedCookieException; @@ -37,7 +38,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicCommentHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { public BasicCommentHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicDomainHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicDomainHandler.java index 7503971b5b..c5e902e35e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicDomainHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicDomainHandler.java @@ -28,7 +28,8 @@ import java.util.Locale; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.InetAddressUtils; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; @@ -44,7 +45,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicDomainHandler implements CommonCookieAttributeHandler { public BasicDomainHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicExpiresHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicExpiresHandler.java index 21a28766e9..2db2194e91 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicExpiresHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicExpiresHandler.java @@ -28,7 +28,8 @@ import java.util.Date; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.utils.DateUtils; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; @@ -40,7 +41,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicExpiresHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { /** Valid date patterns */ diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicMaxAgeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicMaxAgeHandler.java index 02ee8babbf..0914bf6f0b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicMaxAgeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicMaxAgeHandler.java @@ -28,7 +28,8 @@ import java.util.Date; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.MalformedCookieException; @@ -39,7 +40,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicMaxAgeHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { public BasicMaxAgeHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java index c7b3875672..4a435cf1d8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -41,7 +42,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicPathHandler implements CommonCookieAttributeHandler { public BasicPathHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicSecureHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicSecureHandler.java index 5b8f55cc87..9d782a4c99 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicSecureHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicSecureHandler.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -39,7 +40,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class BasicSecureHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { public BasicSecureHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java b/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java index f4f98f1916..5fca8bd3b2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/CookieSpecBase.java @@ -34,7 +34,8 @@ import org.apache.http.HeaderElement; import org.apache.http.NameValuePair; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieAttributeHandler; @@ -47,7 +48,7 @@ * * @since 4.0 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public abstract class CookieSpecBase extends AbstractCookieSpec { public CookieSpecBase() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java index bd571ced48..c291f1c41c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java @@ -32,7 +32,8 @@ import org.apache.http.FormattedHeader; import org.apache.http.Header; import org.apache.http.HeaderElement; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; import org.apache.http.cookie.CookieSpec; @@ -49,7 +50,7 @@ * * @since 4.4 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class DefaultCookieSpec implements CookieSpec { private final RFC2965Spec strict; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpecProvider.java b/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpecProvider.java index 1fe8f0345d..4aa213fa82 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpecProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpecProvider.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; @@ -43,7 +44,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class DefaultCookieSpecProvider implements CookieSpecProvider { public enum CompatibilityLevel { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java index 71bf7902fe..579b8d8050 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpec.java @@ -31,7 +31,8 @@ import java.util.List; import org.apache.http.Header; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; import org.apache.http.cookie.MalformedCookieException; @@ -41,7 +42,7 @@ * * @since 4.1 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class IgnoreSpec extends CookieSpecBase { @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpecProvider.java b/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpecProvider.java index 97bedf6d10..063958be71 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpecProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/IgnoreSpecProvider.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecProvider; import org.apache.http.protocol.HttpContext; @@ -37,7 +38,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class IgnoreSpecProvider implements CookieSpecProvider { private volatile CookieSpec cookieSpec; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java index 82e891c980..8043bb48af 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java @@ -35,7 +35,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.MalformedCookieException; @@ -47,7 +48,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class LaxExpiresHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { static final TimeZone UTC = TimeZone.getTimeZone("UTC"); diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxMaxAgeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxMaxAgeHandler.java index 8615286e87..e4404699d4 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxMaxAgeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxMaxAgeHandler.java @@ -30,7 +30,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.MalformedCookieException; @@ -42,7 +43,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class LaxMaxAgeHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { private final static Pattern MAX_AGE_PATTERN = Pattern.compile("^\\-?[0-9]+$"); diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDomainHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDomainHandler.java index 1f92cc08d4..c187d4ae8b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDomainHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDomainHandler.java @@ -29,7 +29,8 @@ import java.util.Locale; import java.util.StringTokenizer; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; @@ -43,7 +44,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NetscapeDomainHandler extends BasicDomainHandler { public NetscapeDomainHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftHeaderParser.java b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftHeaderParser.java index a6a40de770..3c13a67f23 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftHeaderParser.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftHeaderParser.java @@ -34,7 +34,8 @@ import org.apache.http.HeaderElement; import org.apache.http.NameValuePair; import org.apache.http.ParseException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.message.BasicHeaderElement; import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.ParserCursor; @@ -46,7 +47,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NetscapeDraftHeaderParser { public final static NetscapeDraftHeaderParser DEFAULT = new NetscapeDraftHeaderParser(); diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpec.java index caedd83ad5..968db73a70 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpec.java @@ -33,8 +33,9 @@ import org.apache.http.FormattedHeader; import org.apache.http.Header; import org.apache.http.HeaderElement; +import org.apache.http.annotation.Contract; import org.apache.http.annotation.Obsolete; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; @@ -57,7 +58,7 @@ * @see org.apache.http.impl.cookie.RFC6265LaxSpec */ @Obsolete -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class NetscapeDraftSpec extends CookieSpecBase { protected static final String EXPIRES_PATTERN = "EEE, dd-MMM-yy HH:mm:ss z"; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpecProvider.java b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpecProvider.java index f4832f7717..06b9b8e5d8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpecProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpecProvider.java @@ -27,8 +27,9 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; import org.apache.http.annotation.Obsolete; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecProvider; import org.apache.http.protocol.HttpContext; @@ -44,7 +45,7 @@ * @see org.apache.http.impl.cookie.RFC6265CookieSpecProvider */ @Obsolete -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NetscapeDraftSpecProvider implements CookieSpecProvider { private final String[] datepatterns; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java index 062f8ec6af..24d37283ce 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java @@ -29,7 +29,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.PublicSuffixList; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.cookie.CommonCookieAttributeHandler; @@ -50,7 +51,7 @@ * * @since 4.4 */ -@Immutable // dependencies are expected to be immutable or thread-safe +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class PublicSuffixDomainFilter implements CommonCookieAttributeHandler { private final CommonCookieAttributeHandler handler; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109DomainHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109DomainHandler.java index fdbeb15329..e0a0b8a3f7 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109DomainHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109DomainHandler.java @@ -28,7 +28,8 @@ import java.util.Locale; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -42,7 +43,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RFC2109DomainHandler implements CommonCookieAttributeHandler { public RFC2109DomainHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java index 1b4e783eff..668839c8e8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java @@ -33,8 +33,9 @@ import org.apache.http.Header; import org.apache.http.HeaderElement; +import org.apache.http.annotation.Contract; import org.apache.http.annotation.Obsolete; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.utils.DateUtils; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; @@ -57,7 +58,7 @@ * @see org.apache.http.impl.cookie.RFC6265StrictSpec */ @Obsolete -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class RFC2109Spec extends CookieSpecBase { final static String[] DATE_PATTERNS = { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109SpecProvider.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109SpecProvider.java index c7f9724822..2390a447a8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109SpecProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109SpecProvider.java @@ -27,8 +27,9 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; import org.apache.http.annotation.Obsolete; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecProvider; @@ -45,7 +46,7 @@ * @see org.apache.http.impl.cookie.RFC6265CookieSpecProvider */ @Obsolete -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class RFC2109SpecProvider implements CookieSpecProvider { private final PublicSuffixMatcher publicSuffixMatcher; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109VersionHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109VersionHandler.java index a342e851a3..888a6f5d30 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109VersionHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109VersionHandler.java @@ -26,7 +26,8 @@ */ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -40,7 +41,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RFC2109VersionHandler extends AbstractCookieAttributeHandler implements CommonCookieAttributeHandler { public RFC2109VersionHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965CommentUrlAttributeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965CommentUrlAttributeHandler.java index dd739bce52..db6b7d2d6c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965CommentUrlAttributeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965CommentUrlAttributeHandler.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -41,7 +42,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RFC2965CommentUrlAttributeHandler implements CommonCookieAttributeHandler { public RFC2965CommentUrlAttributeHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DiscardAttributeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DiscardAttributeHandler.java index 62d1f453ed..4ffd574c03 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DiscardAttributeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DiscardAttributeHandler.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -41,7 +42,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RFC2965DiscardAttributeHandler implements CommonCookieAttributeHandler { public RFC2965DiscardAttributeHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DomainAttributeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DomainAttributeHandler.java index 42e790e56a..ee98a1b4a2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DomainAttributeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965DomainAttributeHandler.java @@ -29,7 +29,8 @@ import java.util.Locale; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -45,7 +46,7 @@ * * @since 3.1 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RFC2965DomainAttributeHandler implements CommonCookieAttributeHandler { public RFC2965DomainAttributeHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965PortAttributeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965PortAttributeHandler.java index 004f25473c..e3fdc8eb65 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965PortAttributeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965PortAttributeHandler.java @@ -29,7 +29,8 @@ import java.util.StringTokenizer; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -45,7 +46,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RFC2965PortAttributeHandler implements CommonCookieAttributeHandler { public RFC2965PortAttributeHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java index ca836c12ea..08fd4e85aa 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java @@ -35,8 +35,9 @@ import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.NameValuePair; +import org.apache.http.annotation.Contract; import org.apache.http.annotation.Obsolete; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -57,7 +58,7 @@ * @see org.apache.http.impl.cookie.RFC6265StrictSpec */ @Obsolete -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class RFC2965Spec extends RFC2109Spec { /** diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965SpecProvider.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965SpecProvider.java index ba303a67d7..4c6d932ca1 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965SpecProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965SpecProvider.java @@ -27,8 +27,9 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; import org.apache.http.annotation.Obsolete; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.cookie.CookieSpec; import org.apache.http.cookie.CookieSpecProvider; @@ -45,7 +46,7 @@ * @see org.apache.http.impl.cookie.RFC6265CookieSpecProvider */ @Obsolete -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class RFC2965SpecProvider implements CookieSpecProvider { private final PublicSuffixMatcher publicSuffixMatcher; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965VersionAttributeHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965VersionAttributeHandler.java index ac682d8cb0..9833a0ec5a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965VersionAttributeHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965VersionAttributeHandler.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -43,7 +44,7 @@ * * @since 4.0 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE) public class RFC2965VersionAttributeHandler implements CommonCookieAttributeHandler { public RFC2965VersionAttributeHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java index 22d7d1dbd3..7368dcfe2f 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java @@ -39,7 +39,8 @@ import org.apache.http.FormattedHeader; import org.apache.http.Header; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.ClientCookie; import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; @@ -60,7 +61,7 @@ * * @since 4.5 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class RFC6265CookieSpec implements CookieSpec { private final static char PARAM_DELIMITER = ';'; diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpecProvider.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpecProvider.java index e4f24dc178..69bedce5c3 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpecProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpecProvider.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; @@ -43,7 +44,7 @@ * * @since 4.4 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class RFC6265CookieSpecProvider implements CookieSpecProvider { public enum CompatibilityLevel { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265LaxSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265LaxSpec.java index 8455c83429..56b26daa77 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265LaxSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265LaxSpec.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.cookie.CommonCookieAttributeHandler; /** @@ -38,7 +39,7 @@ * * @since 4.4 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class RFC6265LaxSpec extends RFC6265CookieSpecBase { public RFC6265LaxSpec() { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265StrictSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265StrictSpec.java index 1765d276f3..635b3f5498 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265StrictSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265StrictSpec.java @@ -27,7 +27,8 @@ package org.apache.http.impl.cookie; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.utils.DateUtils; import org.apache.http.cookie.CommonCookieAttributeHandler; @@ -38,7 +39,7 @@ * * @since 4.4 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) public class RFC6265StrictSpec extends RFC6265CookieSpecBase { final static String[] DATE_PATTERNS = { diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/BackoffStrategyExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/BackoffStrategyExec.java index 7c9025b5ba..598c62f2c7 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/BackoffStrategyExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/BackoffStrategyExec.java @@ -31,7 +31,8 @@ import java.lang.reflect.UndeclaredThrowableException; import org.apache.http.HttpException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.BackoffManager; import org.apache.http.client.ConnectionBackoffStrategy; import org.apache.http.client.methods.CloseableHttpResponse; @@ -44,7 +45,7 @@ /** * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class BackoffStrategyExec implements ClientExecChain { private final ClientExecChain requestExecutor; diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java index 0f6e4f3e85..daa5a319fc 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java @@ -34,7 +34,8 @@ import org.apache.commons.logging.Log; import org.apache.http.HttpClientConnection; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.concurrent.Cancellable; import org.apache.http.conn.ConnectionReleaseTrigger; import org.apache.http.conn.HttpClientConnectionManager; @@ -44,7 +45,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.SAFE) class ConnectionHolder implements ConnectionReleaseTrigger, Cancellable, Closeable { private final Log log; diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java index 0184ec2500..533eb704fc 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java @@ -36,7 +36,6 @@ import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.params.HttpParams; @@ -46,7 +45,6 @@ * * @since 4.3 */ -@NotThreadSafe class HttpResponseProxy implements CloseableHttpResponse { private final HttpResponse original; diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java index 9496813005..a932a08c1d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java @@ -42,7 +42,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthProtocolState; import org.apache.http.auth.AuthState; @@ -84,7 +85,7 @@ * @since 4.3 */ @SuppressWarnings("deprecation") -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class MainClientExec implements ClientExecChain { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java index adca0a25eb..bc82904385 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java @@ -44,7 +44,8 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; @@ -77,7 +78,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class MinimalClientExec implements ClientExecChain { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ProtocolExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ProtocolExec.java index 0f9b75c57f..ea3da2c97d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ProtocolExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ProtocolExec.java @@ -37,7 +37,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.ProtocolException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; @@ -69,7 +70,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) @SuppressWarnings("deprecation") public class ProtocolExec implements ClientExecChain { diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java index dcafdb55ca..37549e1c0b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java @@ -38,7 +38,8 @@ import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.ProtocolException; -import org.apache.http.annotation.ThreadSafe; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthState; import org.apache.http.client.RedirectException; @@ -65,7 +66,7 @@ * * @since 4.3 */ -@ThreadSafe +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class RedirectExec implements ClientExecChain { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestAbortedException.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestAbortedException.java index 2a3d0a5f36..4ccde500ab 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestAbortedException.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestAbortedException.java @@ -29,14 +29,11 @@ import java.io.InterruptedIOException; -import org.apache.http.annotation.Immutable; - /** * Signals that the request has been aborted. * * @since 4.3 */ -@Immutable public class RequestAbortedException extends InterruptedIOException { private static final long serialVersionUID = 4973849966012490112L; diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java index e4ed35b669..1affd94a97 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java @@ -34,14 +34,12 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; -import org.apache.http.annotation.NotThreadSafe; /** * A Proxy class for {@link org.apache.http.HttpEntity} enclosed in a request message. * * @since 4.3 */ -@NotThreadSafe class RequestEntityProxy implements HttpEntity { static void enhance(final HttpEntityEnclosingRequest request) { diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java index ba2716326e..7013e09ebd 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java @@ -34,7 +34,6 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; import org.apache.http.conn.EofSensorInputStream; import org.apache.http.conn.EofSensorWatcher; import org.apache.http.entity.HttpEntityWrapper; @@ -44,7 +43,6 @@ * * @since 4.3 */ -@NotThreadSafe class ResponseEntityProxy extends HttpEntityWrapper implements EofSensorWatcher { private final ConnectionHolder connHolder; diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java index cade16405a..201733e9bb 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java @@ -34,7 +34,8 @@ import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.NoHttpResponseException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.NonRepeatableRequestException; import org.apache.http.client.methods.CloseableHttpResponse; @@ -56,7 +57,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class RetryExec implements ClientExecChain { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java index 6fb6ef39d0..8b0c6f4342 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java @@ -34,7 +34,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.Header; import org.apache.http.HttpException; -import org.apache.http.annotation.Immutable; +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.ServiceUnavailableRetryStrategy; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; @@ -55,7 +56,7 @@ * * @since 4.3 */ -@Immutable +@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class ServiceUnavailableRetryExec implements ClientExecChain { private final Log log = LogFactory.getLog(getClass()); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/TunnelRefusedException.java b/httpclient/src/main/java/org/apache/http/impl/execchain/TunnelRefusedException.java index cff1e07972..1b993ac071 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/TunnelRefusedException.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/TunnelRefusedException.java @@ -29,14 +29,12 @@ import org.apache.http.HttpException; import org.apache.http.HttpResponse; -import org.apache.http.annotation.Immutable; /** * Signals that the tunnel request was rejected by the proxy host. * * @since 4.0 */ -@Immutable public class TunnelRefusedException extends HttpException { private static final long serialVersionUID = -8646722842745617323L; diff --git a/pom.xml b/pom.xml index 8a12f46eff..a5b9d79fac 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 1.6 1.6 - 4.4.4 + 4.4.5 1.2 1.9 2.6.9 From e8002ae3b9bbc72467ed5223b929e4a00d1aca5c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 7 Jan 2017 11:30:28 +0000 Subject: [PATCH 093/204] HTTPCLIENT-1800: wrap redirect around retry in execChain git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1777766 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/impl/client/HttpClientBuilder.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 507f7d390d..294135d396 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -1148,6 +1148,13 @@ public CloseableHttpClient build() { routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy); } } + + // Optionally, add service unavailable retry executor + final ServiceUnavailableRetryStrategy serviceUnavailStrategyCopy = this.serviceUnavailStrategy; + if (serviceUnavailStrategyCopy != null) { + execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategyCopy); + } + // Add redirect executor, if not disabled if (!redirectHandlingDisabled) { RedirectStrategy redirectStrategyCopy = this.redirectStrategy; @@ -1157,11 +1164,6 @@ public CloseableHttpClient build() { execChain = new RedirectExec(execChain, routePlannerCopy, redirectStrategyCopy); } - // Optionally, add service unavailable retry executor - final ServiceUnavailableRetryStrategy serviceUnavailStrategyCopy = this.serviceUnavailStrategy; - if (serviceUnavailStrategyCopy != null) { - execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategyCopy); - } // Optionally, add connection back-off executor if (this.backoffManager != null && this.connectionBackoffStrategy != null) { execChain = new BackoffStrategyExec(execChain, this.connectionBackoffStrategy, this.backoffManager); From 13810dd84c3c6f908163883145b5321ba622d6db Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 12 Jan 2017 10:07:05 +0000 Subject: [PATCH 094/204] Upgraded HttpCore to version 4.4.6 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1778408 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a5b9d79fac..979a427a3d 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 1.6 1.6 - 4.4.5 + 4.4.6 1.2 1.9 2.6.9 From bc5d688a4f320cb048852fa66a436b29c67c0061 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 12 Jan 2017 10:07:29 +0000 Subject: [PATCH 095/204] HTTPCLIENT-1792: SSLConnectionSocketFactory to throw SSLPeerUnverifiedException with a better error message when hostname verification fails git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1778409 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/conn/ssl/AbstractVerifier.java | 13 ++-- .../conn/ssl/DefaultHostnameVerifier.java | 60 ++++++++++++------- .../conn/ssl/SSLConnectionSocketFactory.java | 6 +- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java index 5950dff018..b865526ed0 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -132,9 +132,14 @@ public final boolean verify(final String host, final SSLSession session) { @Override public final void verify( final String host, final X509Certificate cert) throws SSLException { - final boolean ipv4 = InetAddressUtils.isIPv4Address(host); - final boolean ipv6 = InetAddressUtils.isIPv6Address(host); - final int subjectType = ipv4 || ipv6 ? DefaultHostnameVerifier.IP_ADDRESS_TYPE : DefaultHostnameVerifier.DNS_NAME_TYPE; + final int subjectType; + if (InetAddressUtils.isIPv4Address(host)) { + subjectType = DefaultHostnameVerifier.HostNameType.IPv4.subjectType; + } else if (InetAddressUtils.isIPv6Address(host)) { + subjectType = DefaultHostnameVerifier.HostNameType.IPv6.subjectType; + } else { + subjectType = DefaultHostnameVerifier.HostNameType.DNS.subjectType; + } final List subjectAlts = DefaultHostnameVerifier.extractSubjectAlts(cert, subjectType); final X500Principal subjectPrincipal = cert.getSubjectX500Principal(); final String cn = DefaultHostnameVerifier.extractCN(subjectPrincipal.getName(X500Principal.RFC2253)); @@ -246,7 +251,7 @@ public static String[] getCNs(final X509Certificate cert) { */ public static String[] getDNSSubjectAlts(final X509Certificate cert) { final List subjectAlts = DefaultHostnameVerifier.extractSubjectAlts( - cert, DefaultHostnameVerifier.DNS_NAME_TYPE); + cert, DefaultHostnameVerifier.HostNameType.DNS.subjectType); return subjectAlts != null && !subjectAlts.isEmpty() ? subjectAlts.toArray(new String[subjectAlts.size()]) : null; } diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 64b63f731e..d9a2444ccb 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -46,6 +46,7 @@ import javax.naming.ldap.Rdn; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; import javax.security.auth.x500.X500Principal; @@ -65,10 +66,17 @@ @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public final class DefaultHostnameVerifier implements HostnameVerifier { - enum TYPE { IPv4, IPv6, DNS } + enum HostNameType { - final static int DNS_NAME_TYPE = 2; - final static int IP_ADDRESS_TYPE = 7; + IPv4(7), IPv6(7), DNS(2); + + final int subjectType; + + HostNameType(final int subjectType) { + this.subjectType = subjectType; + } + + } private final Log log = LogFactory.getLog(getClass()); @@ -99,22 +107,10 @@ public boolean verify(final String host, final SSLSession session) { public void verify( final String host, final X509Certificate cert) throws SSLException { - TYPE hostFormat = TYPE.DNS; - if (InetAddressUtils.isIPv4Address(host)) { - hostFormat = TYPE.IPv4; - } else { - String s = host; - if (s.startsWith("[") && s.endsWith("]")) { - s = host.substring(1, host.length() - 1); - } - if (InetAddressUtils.isIPv6Address(s)) { - hostFormat = TYPE.IPv6; - } - } - final int subjectType = hostFormat == TYPE.IPv4 || hostFormat == TYPE.IPv6 ? IP_ADDRESS_TYPE : DNS_NAME_TYPE; - final List subjectAlts = extractSubjectAlts(cert, subjectType); + final HostNameType hostType = determineHostFormat(host); + final List subjectAlts = extractSubjectAlts(cert, hostType.subjectType); if (subjectAlts != null && !subjectAlts.isEmpty()) { - switch (hostFormat) { + switch (hostType) { case IPv4: matchIPAddress(host, subjectAlts); break; @@ -144,7 +140,7 @@ static void matchIPAddress(final String host, final List subjectAlts) th return; } } - throw new SSLException("Certificate for <" + host + "> doesn't match any " + + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + "of the subject alternative names: " + subjectAlts); } @@ -157,7 +153,7 @@ static void matchIPv6Address(final String host, final List subjectAlts) return; } } - throw new SSLException("Certificate for <" + host + "> doesn't match any " + + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + "of the subject alternative names: " + subjectAlts); } @@ -171,7 +167,7 @@ static void matchDNSName(final String host, final List subjectAlts, return; } } - throw new SSLException("Certificate for <" + host + "> doesn't match any " + + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + "of the subject alternative names: " + subjectAlts); } @@ -180,7 +176,7 @@ static void matchCN(final String host, final String cn, final String normalizedHost = host.toLowerCase(Locale.ROOT); final String normalizedCn = cn.toLowerCase(Locale.ROOT); if (!matchIdentityStrict(normalizedHost, normalizedCn, publicSuffixMatcher)) { - throw new SSLException("Certificate for <" + host + "> doesn't match " + + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match " + "common name of the certificate subject: " + cn); } } @@ -278,6 +274,21 @@ static String extractCN(final String subjectPrincipal) throws SSLException { } } + static HostNameType determineHostFormat(final String host) { + if (InetAddressUtils.isIPv4Address(host)) { + return HostNameType.IPv4; + } else { + String s = host; + if (s.startsWith("[") && s.endsWith("]")) { + s = host.substring(1, host.length() - 1); + } + if (InetAddressUtils.isIPv6Address(s)) { + return HostNameType.IPv6; + } + } + return HostNameType.DNS; + } + static List extractSubjectAlts(final X509Certificate cert, final int subjectType) { Collection> c = null; try { @@ -302,6 +313,11 @@ static List extractSubjectAlts(final X509Certificate cert, final int sub return subjectAltList; } + static List extractSubjectAlts(final String host, final X509Certificate cert) { + final HostNameType hostType = determineHostFormat(host); + return extractSubjectAlts(cert, hostType.subjectType); + } + /* * Normalize IPv6 or DNS name. */ diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java index 504f24adab..20a86327dd 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java @@ -463,9 +463,9 @@ private void verifyHostname(final SSLSocket sslsock, final String hostname) thro if (!this.hostnameVerifier.verify(hostname, session)) { final Certificate[] certs = session.getPeerCertificates(); final X509Certificate x509 = (X509Certificate) certs[0]; - final X500Principal x500Principal = x509.getSubjectX500Principal(); - throw new SSLPeerUnverifiedException("Host name '" + hostname + "' does not match " + - "the certificate subject provided by the peer (" + x500Principal.toString() + ")"); + final List subjectAlts = DefaultHostnameVerifier.extractSubjectAlts(hostname, x509); + throw new SSLPeerUnverifiedException("Certificate for <" + hostname + "> doesn't match any " + + "of the subject alternative names: " + subjectAlts); } // verifyHostName() didn't blowup - good! } catch (final IOException iox) { From 75f7b398ea64cf5bbef0bc3e4cb6ba65fdc1ea53 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 12 Jan 2017 10:07:41 +0000 Subject: [PATCH 096/204] HTTPCLIENT-1777: fixed binary compatibility with 4.4 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1778410 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/HttpProxyConfigurationActivator.java | 4 +- ... OSGiCachingHttpClientBuilderFactory.java} | 7 +-- .../osgi/impl/OSGiClientBuilderFactory.java | 41 ++++++++----- .../impl/OSGiHttpClientBuilderFactory.java | 57 +++++++++++++++++++ 4 files changed, 89 insertions(+), 20 deletions(-) rename httpclient-osgi/src/main/java/org/apache/http/osgi/impl/{OSGiCachingClientBuilderFactory.java => OSGiCachingHttpClientBuilderFactory.java} (93%) create mode 100644 httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilderFactory.java diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index ae2d8c7e80..16d5c1bf58 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -100,7 +100,7 @@ public void start(final BundleContext context) throws Exception { props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, BUILDER_FACTORY_SERVICE_NAME); clientFactory = context.registerService(HttpClientBuilderFactory.class.getName(), - new OSGiClientBuilderFactory(configurator, httpClientTracker), + new OSGiHttpClientBuilderFactory(configurator, httpClientTracker), props); props.clear(); @@ -108,7 +108,7 @@ public void start(final BundleContext context) throws Exception { props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR)); props.put(Constants.SERVICE_DESCRIPTION, CACHEABLE_BUILDER_FACTORY_SERVICE_NAME); cachingClientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(), - new OSGiCachingClientBuilderFactory(configurator, httpClientTracker), + new OSGiCachingHttpClientBuilderFactory(configurator, httpClientTracker), props); } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilderFactory.java similarity index 93% rename from httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java rename to httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilderFactory.java index 80661c83c6..4d505a51bb 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingClientBuilderFactory.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiCachingHttpClientBuilderFactory.java @@ -30,16 +30,13 @@ import org.apache.http.impl.client.cache.CachingHttpClientBuilder; import org.apache.http.osgi.services.CachingHttpClientBuilderFactory; -/** - * @since 4.3 - */ -final class OSGiCachingClientBuilderFactory implements CachingHttpClientBuilderFactory { +final class OSGiCachingHttpClientBuilderFactory implements CachingHttpClientBuilderFactory { private final HttpClientBuilderConfigurator configurator; private final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker; - OSGiCachingClientBuilderFactory( + OSGiCachingHttpClientBuilderFactory( final HttpClientBuilderConfigurator configurator, final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker) { this.configurator = configurator; diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java index 84a76f86ea..aef9d64905 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiClientBuilderFactory.java @@ -26,35 +26,50 @@ */ package org.apache.http.osgi.impl; +import java.util.List; +import java.util.Map; + import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.osgi.services.HttpClientBuilderFactory; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; /** * @since 4.3 + * + * @deprecated (4.5). No longer used. */ -final class OSGiClientBuilderFactory implements HttpClientBuilderFactory { +@Deprecated +public final class OSGiClientBuilderFactory implements HttpClientBuilderFactory { - private final HttpClientBuilderConfigurator configurator; + private final BundleContext bundleContext; - private final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker; + private final Map registeredConfigurations; - OSGiClientBuilderFactory( - final HttpClientBuilderConfigurator configurator, - final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker) { - this.configurator = configurator; - this.httpClientTracker = httpClientTracker; + private final List trackedHttpClients; + + public OSGiClientBuilderFactory( + final BundleContext bundleContext, + final Map registeredConfigurations, + final List trackedHttpClients) { + this.bundleContext = bundleContext; + this.registeredConfigurations = registeredConfigurations; + this.trackedHttpClients = trackedHttpClients; } @Override public HttpClientBuilder newBuilder() { - return configurator.configure(new HttpClientBuilder() { + return new HttpClientBuilder() { @Override public CloseableHttpClient build() { - final CloseableHttpClient client = super.build(); - httpClientTracker.track(client); - return client; + final CloseableHttpClient httpClient = super.build(); + synchronized (trackedHttpClients) { + trackedHttpClients.add(httpClient); + } + return httpClient; } - }); + }; } + } diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilderFactory.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilderFactory.java new file mode 100644 index 0000000000..628892dc5e --- /dev/null +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpClientBuilderFactory.java @@ -0,0 +1,57 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.osgi.impl; + +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.osgi.services.HttpClientBuilderFactory; + +final class OSGiHttpClientBuilderFactory implements HttpClientBuilderFactory { + + private final HttpClientBuilderConfigurator configurator; + + private final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker; + + OSGiHttpClientBuilderFactory( + final HttpClientBuilderConfigurator configurator, + final HttpProxyConfigurationActivator.HttpClientTracker httpClientTracker) { + this.configurator = configurator; + this.httpClientTracker = httpClientTracker; + } + + @Override + public HttpClientBuilder newBuilder() { + return configurator.configure(new HttpClientBuilder() { + @Override + public CloseableHttpClient build() { + final CloseableHttpClient client = super.build(); + httpClientTracker.track(client); + return client; + } + }); + } +} From b88ab92f7bb8d032dd909428ba9eb03840a26297 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 12 Jan 2017 19:20:44 +0000 Subject: [PATCH 097/204] HTTPCLIENT-1788: RFC 6265 policy must not reject cookies with paths that are no prefix of the uri path git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1778459 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/cookie/BasicPathHandler.java | 6 ------ .../org/apache/http/impl/cookie/RFC2109Spec.java | 14 +++++++++++++- .../org/apache/http/impl/cookie/RFC2965Spec.java | 15 ++++++++++++++- .../cookie/TestBasicCookieAttribHandlers.java | 16 ---------------- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java index 4a435cf1d8..888888986b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/BasicPathHandler.java @@ -32,7 +32,6 @@ import org.apache.http.cookie.CommonCookieAttributeHandler; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; -import org.apache.http.cookie.CookieRestrictionViolationException; import org.apache.http.cookie.MalformedCookieException; import org.apache.http.cookie.SetCookie; import org.apache.http.util.Args; @@ -59,11 +58,6 @@ public void parse( @Override public void validate(final Cookie cookie, final CookieOrigin origin) throws MalformedCookieException { - if (!match(cookie, origin)) { - throw new CookieRestrictionViolationException( - "Illegal 'path' attribute \"" + cookie.getPath() - + "\". Path of origin: \"" + origin.getPath() + "\""); - } } static boolean pathMatch(final String uriPath, final String cookiePath) { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java index 668839c8e8..cee6d965f3 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java @@ -72,7 +72,19 @@ public class RFC2109Spec extends CookieSpecBase { /** Default constructor */ public RFC2109Spec(final String[] datepatterns, final boolean oneHeader) { super(new RFC2109VersionHandler(), - new BasicPathHandler(), + new BasicPathHandler() { + + @Override + public void validate( + final Cookie cookie, final CookieOrigin origin) throws MalformedCookieException { + if (!match(cookie, origin)) { + throw new CookieRestrictionViolationException( + "Illegal 'path' attribute \"" + cookie.getPath() + + "\". Path of origin: \"" + origin.getPath() + "\""); + } + } + + }, new RFC2109DomainHandler(), new BasicMaxAgeHandler(), new BasicSecureHandler(), diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java index 08fd4e85aa..5fca006ad0 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java @@ -43,6 +43,7 @@ import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieAttributeHandler; import org.apache.http.cookie.CookieOrigin; +import org.apache.http.cookie.CookieRestrictionViolationException; import org.apache.http.cookie.MalformedCookieException; import org.apache.http.cookie.SM; import org.apache.http.message.BufferedHeader; @@ -72,7 +73,19 @@ public RFC2965Spec() { public RFC2965Spec(final String[] datepatterns, final boolean oneHeader) { super(oneHeader, new RFC2965VersionAttributeHandler(), - new BasicPathHandler(), + new BasicPathHandler() { + + @Override + public void validate( + final Cookie cookie, final CookieOrigin origin) throws MalformedCookieException { + if (!match(cookie, origin)) { + throw new CookieRestrictionViolationException( + "Illegal 'path' attribute \"" + cookie.getPath() + + "\". Path of origin: \"" + origin.getPath() + "\""); + } + } + + }, new RFC2965DomainAttributeHandler(), new RFC2965PortAttributeHandler(), new BasicMaxAgeHandler(), diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java index 4da73d1765..213029c856 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java @@ -297,22 +297,6 @@ public void testBasicPathMatch7() throws Exception { Assert.assertTrue(h.match(cookie, origin)); } - @Test - public void testBasicPathValidate() throws Exception { - final BasicClientCookie cookie = new BasicClientCookie("name", "value"); - final CookieOrigin origin = new CookieOrigin("somehost", 80, "/stuff", false); - final CookieAttributeHandler h = new BasicPathHandler(); - cookie.setPath("/stuff"); - h.validate(cookie, origin); - cookie.setPath("/stuffed"); - try { - h.validate(cookie, origin); - Assert.fail("MalformedCookieException must have been thrown"); - } catch (final MalformedCookieException ex) { - // expected - } - } - @Test public void testBasicPathInvalidInput() throws Exception { final CookieAttributeHandler h = new BasicPathHandler(); From 6e4759800fe8a82ee1e9f860c7b8f570dc503913 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 20 Jan 2017 19:20:31 +0000 Subject: [PATCH 098/204] HTTPCLIENT-1802: Do not attempt to match SSL host to subject CN if subject alternative name of any type are given git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1779668 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/conn/ssl/AbstractVerifier.java | 36 ++++++--- .../conn/ssl/DefaultHostnameVerifier.java | 74 +++++++++---------- .../conn/ssl/SSLConnectionSocketFactory.java | 2 +- .../org/apache/http/conn/ssl/SubjectName.java | 65 ++++++++++++++++ .../http/conn/ssl/CertificatesToPlayWith.java | 41 ++++++++++ .../conn/ssl/TestDefaultHostnameVerifier.java | 27 +++++-- 6 files changed, 189 insertions(+), 56 deletions(-) create mode 100644 httpclient/src/main/java/org/apache/http/conn/ssl/SubjectName.java diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java index b865526ed0..ef56890e7c 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -31,6 +31,7 @@ import java.io.InputStream; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -132,15 +133,21 @@ public final boolean verify(final String host, final SSLSession session) { @Override public final void verify( final String host, final X509Certificate cert) throws SSLException { - final int subjectType; - if (InetAddressUtils.isIPv4Address(host)) { - subjectType = DefaultHostnameVerifier.HostNameType.IPv4.subjectType; - } else if (InetAddressUtils.isIPv6Address(host)) { - subjectType = DefaultHostnameVerifier.HostNameType.IPv6.subjectType; + final List allSubjectAltNames = DefaultHostnameVerifier.getSubjectAltNames(cert); + final List subjectAlts = new ArrayList(); + if (InetAddressUtils.isIPv4Address(host) || InetAddressUtils.isIPv6Address(host)) { + for (SubjectName subjectName: allSubjectAltNames) { + if (subjectName.getType() == SubjectName.IP) { + subjectAlts.add(subjectName.getValue()); + } + } } else { - subjectType = DefaultHostnameVerifier.HostNameType.DNS.subjectType; + for (SubjectName subjectName: allSubjectAltNames) { + if (subjectName.getType() == SubjectName.DNS) { + subjectAlts.add(subjectName.getValue()); + } + } } - final List subjectAlts = DefaultHostnameVerifier.extractSubjectAlts(cert, subjectType); final X500Principal subjectPrincipal = cert.getSubjectX500Principal(); final String cn = DefaultHostnameVerifier.extractCN(subjectPrincipal.getName(X500Principal.RFC2253)); verify(host, @@ -250,10 +257,17 @@ public static String[] getCNs(final X509Certificate cert) { * @return Array of SubjectALT DNS names stored in the certificate. */ public static String[] getDNSSubjectAlts(final X509Certificate cert) { - final List subjectAlts = DefaultHostnameVerifier.extractSubjectAlts( - cert, DefaultHostnameVerifier.HostNameType.DNS.subjectType); - return subjectAlts != null && !subjectAlts.isEmpty() ? - subjectAlts.toArray(new String[subjectAlts.size()]) : null; + final List subjectAltNames = DefaultHostnameVerifier.getSubjectAltNames(cert); + if (subjectAltNames == null) { + return null; + } + final List dnsAlts = new ArrayList(); + for (SubjectName subjectName: subjectAltNames) { + if (subjectName.getType() == SubjectName.DNS) { + dnsAlts.add(subjectName.getValue()); + } + } + return dnsAlts.isEmpty() ? dnsAlts.toArray(new String[dnsAlts.size()]) : null; } /** diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index d9a2444ccb..2844f3b67a 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -34,6 +34,7 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.NoSuchElementException; @@ -108,7 +109,7 @@ public boolean verify(final String host, final SSLSession session) { public void verify( final String host, final X509Certificate cert) throws SSLException { final HostNameType hostType = determineHostFormat(host); - final List subjectAlts = extractSubjectAlts(cert, hostType.subjectType); + final List subjectAlts = getSubjectAltNames(cert); if (subjectAlts != null && !subjectAlts.isEmpty()) { switch (hostType) { case IPv4: @@ -133,38 +134,44 @@ public void verify( } } - static void matchIPAddress(final String host, final List subjectAlts) throws SSLException { + static void matchIPAddress(final String host, final List subjectAlts) throws SSLException { for (int i = 0; i < subjectAlts.size(); i++) { - final String subjectAlt = subjectAlts.get(i); - if (host.equals(subjectAlt)) { - return; + final SubjectName subjectAlt = subjectAlts.get(i); + if (subjectAlt.getType() == SubjectName.IP) { + if (host.equals(subjectAlt.getValue())) { + return; + } } } throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + "of the subject alternative names: " + subjectAlts); } - static void matchIPv6Address(final String host, final List subjectAlts) throws SSLException { + static void matchIPv6Address(final String host, final List subjectAlts) throws SSLException { final String normalisedHost = normaliseAddress(host); for (int i = 0; i < subjectAlts.size(); i++) { - final String subjectAlt = subjectAlts.get(i); - final String normalizedSubjectAlt = normaliseAddress(subjectAlt); - if (normalisedHost.equals(normalizedSubjectAlt)) { - return; + final SubjectName subjectAlt = subjectAlts.get(i); + if (subjectAlt.getType() == SubjectName.IP) { + final String normalizedSubjectAlt = normaliseAddress(subjectAlt.getValue()); + if (normalisedHost.equals(normalizedSubjectAlt)) { + return; + } } } throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + "of the subject alternative names: " + subjectAlts); } - static void matchDNSName(final String host, final List subjectAlts, + static void matchDNSName(final String host, final List subjectAlts, final PublicSuffixMatcher publicSuffixMatcher) throws SSLException { final String normalizedHost = host.toLowerCase(Locale.ROOT); for (int i = 0; i < subjectAlts.size(); i++) { - final String subjectAlt = subjectAlts.get(i); - final String normalizedSubjectAlt = subjectAlt.toLowerCase(Locale.ROOT); - if (matchIdentityStrict(normalizedHost, normalizedSubjectAlt, publicSuffixMatcher)) { - return; + final SubjectName subjectAlt = subjectAlts.get(i); + if (subjectAlt.getType() == SubjectName.DNS) { + final String normalizedSubjectAlt = subjectAlt.getValue().toLowerCase(Locale.ROOT); + if (matchIdentityStrict(normalizedHost, normalizedSubjectAlt, publicSuffixMatcher)) { + return; + } } } throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + @@ -289,33 +296,24 @@ static HostNameType determineHostFormat(final String host) { return HostNameType.DNS; } - static List extractSubjectAlts(final X509Certificate cert, final int subjectType) { - Collection> c = null; + static List getSubjectAltNames(final X509Certificate cert) { try { - c = cert.getSubjectAlternativeNames(); - } catch(final CertificateParsingException ignore) { - return null; - } - List subjectAltList = null; - if (c != null) { - for (final List aC : c) { - final List list = aC; - final int type = ((Integer) list.get(0)).intValue(); - if (type == subjectType) { - final String s = (String) list.get(1); - if (subjectAltList == null) { - subjectAltList = new ArrayList(); - } - subjectAltList.add(s); + final Collection> entries = cert.getSubjectAlternativeNames(); + if (entries == null) { + return Collections.emptyList(); + } + final List result = new ArrayList(); + for (List entry: entries) { + final Integer type = entry.size() >= 2 ? (Integer) entry.get(0) : null; + if (type != null) { + final String s = (String) entry.get(1); + result.add(new SubjectName(s, type)); } } + return result; + } catch (final CertificateParsingException ignore) { + return Collections.emptyList(); } - return subjectAltList; - } - - static List extractSubjectAlts(final String host, final X509Certificate cert) { - final HostNameType hostType = determineHostFormat(host); - return extractSubjectAlts(cert, hostType.subjectType); } /* diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java index 20a86327dd..e7f9b28ea3 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java @@ -463,7 +463,7 @@ private void verifyHostname(final SSLSocket sslsock, final String hostname) thro if (!this.hostnameVerifier.verify(hostname, session)) { final Certificate[] certs = session.getPeerCertificates(); final X509Certificate x509 = (X509Certificate) certs[0]; - final List subjectAlts = DefaultHostnameVerifier.extractSubjectAlts(hostname, x509); + final List subjectAlts = DefaultHostnameVerifier.getSubjectAltNames(x509); throw new SSLPeerUnverifiedException("Certificate for <" + hostname + "> doesn't match any " + "of the subject alternative names: " + subjectAlts); } diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SubjectName.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SubjectName.java new file mode 100644 index 0000000000..9da9cdb9b6 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SubjectName.java @@ -0,0 +1,65 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.conn.ssl; + +import org.apache.http.util.Args; + +final class SubjectName { + + static final int DNS = 2; + static final int IP = 7; + + private final String value; + private final int type; + + static SubjectName IP(final String value) { + return new SubjectName(value, IP); + } + + static SubjectName DNS(final String value) { + return new SubjectName(value, DNS); + } + + SubjectName(final String value, final int type) { + this.value = Args.notNull(value, "Value"); + this.type = Args.positive(type, "Type"); + } + + public int getType() { + return type; + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return value; + } + +} diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java b/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java index 4b9d1b9f21..284c111fab 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java @@ -509,4 +509,45 @@ public class CertificatesToPlayWith { "I1mQmUs44cg2HZAqnFBpDyJQhNYy8M7yGVaRkbfuVaMqiPa+xDPR5v7NFB3kxRq2\n" + "Za2Snopi52eUxDEhJ0MNqFi3Jfj/ZSmJ+XHra5lU4R8lijCAq8SVLZCmIQ==\n" + "-----END CERTIFICATE-----").getBytes(); + + public final static byte[] S_GOOGLE_COM = ( + "-----BEGIN CERTIFICATE-----\n" + + "MIICpzCCAY+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAXMRUwEwYDVQQDDAwqLmdv\n" + + "b2dsZS5jb20wHhcNMTcwMTEzMjI0OTAzWhcNMTgwMTEzMjI0OTAzWjAXMRUwEwYD\n" + + "VQQDDAwqLmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n" + + "AQDHuzznuHdJ5PH344xCyGYnUnIRhyLGBKN3WDLLrXWtr/5Sf3Q1qkiMiJ4BINsh\n" + + "3Xy0z7VvHmMFlntgHXtkofBUPvTihxsVIypRkCZb5hpsWLotR10AW2JpVl/oxLP2\n" + + "227/36X1zKh33fjImLJl9KzGWHLsbCBleQQJOn7YRsNR/QBZO0XGGkN/R2rRfLF3\n" + + "rseRfI5gJjZkO0WDxocnf/iieOe0XNR0NAZaY1aozzPmZ/pRrOKYB8OFH7F73WOC\n" + + "lPIUGai/byJ9SpbXdLUcMlGhml/4XzcnV/WVRD2P/mlY+xEFG3UEy3ufhNnKFJul\n" + + "yjZrOaKbagamqtOyktzkjnerAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBADaMcwVs\n" + + "w5kbnoDJzMBJ01H16T4u8k78i/ybwz7u7krgkU0tABXCRj7S/4Dt3jqQ/rV6evj4\n" + + "gIJ/2kZUp/PHKkV7CxWI48XBTAQUu9LEpxj0Hut3AtNMD9y/J6cFn2978tWsHFHI\n" + + "mYgvclKUDE4WFMvuxfQVuX3RcGQ5i8khEMczY/KVhZYDcLU1PU0GTTJqqrQm59Z4\n" + + "T4UyI3OPBR7Nb/kaU1fcgQ083uxRXcNYRMMZnU6c2oFnR+c6pO6aGoXo0C6rgC4R\n" + + "pOj4hPvHCfZO2xg6HAdQ7UPALLX8pu5KGot7GRc8yiJ/Q1nBEuiPKKu0MIwQoFgP\n" + + "WUux/APTsgLR7Vc=\n" + + "-----END CERTIFICATE-----" + ).getBytes(); + + public final static byte[] IP_1_1_1_1 = ( + "-----BEGIN CERTIFICATE-----\n" + + "MIICwjCCAaqgAwIBAgIBATANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDEw9kdW1t\n" + + "eS12YWx1ZS5jb20wHhcNMTcwMTEzMjI1MTQ2WhcNMTgwMTEzMjI1MTQ2WjAaMRgw\n" + + "FgYDVQQDEw9kdW1teS12YWx1ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" + + "ggEKAoIBAQDfrapp3jHLp1RlElzpR/4sF9AcTYwMF1N+adkHRoVtmTlJV2lTIAjn\n" + + "QLauy0Kkzv8uxmbID3uROgrFNDQ5RxTTCe+kW/vE6Pyzr5Z5ayjSTKeycTE7mAC4\n" + + "6ntoCeEWiD593zlfqVo5PuRSp9Kusd+kexNVjC/BETDPa3yXctcH1ouW9GyGItgQ\n" + + "u4GhCE8cipKMuTltgfK+Gh/5e9lFG9/F2fD+wHUVBULLR3JOQoqwgk2zAwKDwLuS\n" + + "sEd1CBi35+W3apCKN0SEdTKIAxc/R+O/1j2hpOl9yXCCYyveGwJdFXVZtDcx+9/H\n" + + "7NXhOdmw/mTXC5fOQGKciEo2SXt8Wp89AgMBAAGjEzARMA8GA1UdEQQIMAaHBAEB\n" + + "AQEwDQYJKoZIhvcNAQEFBQADggEBAEAO6CE8twpcfdjk9oMjI5nX9GdC5Wt6+ujd\n" + + "tLj0SbXvMKzCLLkveT0xTEzXfyEo8KW2qYYvPP1h83BIxsbR/J3Swt35UQVofv+4\n" + + "JgO0FIdgB+iLEcjUh5+60xslylqWE+9bSWm4f06OXuv78tq5NYPZKku/3i4tqLRp\n" + + "gH2rTtjX7Q4olSS7GdAgfiA2AnDZAbMtxtsnTt/QFpYQqhlkqHVDwgkGP7C8aMBD\n" + + "RH0UIQCPxUkhwhtNmVyHO42r6oHXselZoVU6XRHuhogrGxPf/pzDUvrKBiJhsZQQ\n" + + "oEu+pZCwkFLiNwUoq1G2oDpkkdBWB0JcBXB2Txa536ezFFWZYc0=\n" + + "-----END CERTIFICATE-----" + ).getBytes(); + } diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java b/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java index 79fc981a6c..a58f468ee7 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java @@ -149,6 +149,21 @@ public void testVerify() throws Exception { in = new ByteArrayInputStream(CertificatesToPlayWith.X509_MULTIPLE_VALUE_AVA); x509 = (X509Certificate) cf.generateCertificate(in); impl.verify("repository.infonotary.com", x509); + + in = new ByteArrayInputStream(CertificatesToPlayWith.S_GOOGLE_COM); + x509 = (X509Certificate) cf.generateCertificate(in); + impl.verify("*.google.com", x509); + + in = new ByteArrayInputStream(CertificatesToPlayWith.S_GOOGLE_COM); + x509 = (X509Certificate) cf.generateCertificate(in); + impl.verify("*.Google.com", x509); + + in = new ByteArrayInputStream(CertificatesToPlayWith.IP_1_1_1_1); + x509 = (X509Certificate) cf.generateCertificate(in); + impl.verify("1.1.1.1", x509); + + exceptionPlease(impl, "1.1.1.2", x509); + exceptionPlease(impl, "dummy-value.com", x509); } @Test @@ -259,18 +274,18 @@ public void testHTTPCLIENT_1255() { @Test // Check compressed IPv6 hostname matching public void testHTTPCLIENT_1316() throws Exception{ final String host1 = "2001:0db8:aaaa:bbbb:cccc:0:0:0001"; - DefaultHostnameVerifier.matchIPv6Address(host1, Arrays.asList("2001:0db8:aaaa:bbbb:cccc:0:0:0001")); - DefaultHostnameVerifier.matchIPv6Address(host1, Arrays.asList("2001:0db8:aaaa:bbbb:cccc::1")); + DefaultHostnameVerifier.matchIPv6Address(host1, Arrays.asList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc:0:0:0001"))); + DefaultHostnameVerifier.matchIPv6Address(host1, Arrays.asList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::1"))); try { - DefaultHostnameVerifier.matchIPv6Address(host1, Arrays.asList("2001:0db8:aaaa:bbbb:cccc::10")); + DefaultHostnameVerifier.matchIPv6Address(host1, Arrays.asList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::10"))); Assert.fail("SSLException expected"); } catch (final SSLException expected) { } final String host2 = "2001:0db8:aaaa:bbbb:cccc::1"; - DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList("2001:0db8:aaaa:bbbb:cccc:0:0:0001")); - DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList("2001:0db8:aaaa:bbbb:cccc::1")); + DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc:0:0:0001"))); + DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::1"))); try { - DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList("2001:0db8:aaaa:bbbb:cccc::10")); + DefaultHostnameVerifier.matchIPv6Address(host2, Arrays.asList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::10"))); Assert.fail("SSLException expected"); } catch (final SSLException expected) { } From 0554271750599756d4946c0d7ba43d04b1a7b220 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 21 Jan 2017 14:43:44 +0000 Subject: [PATCH 099/204] HTTPCLIENT-1803: Improved handling of malformed paths by URIBuilder git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1779735 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/client/utils/URIBuilder.java | 5 ++++- .../java/org/apache/http/client/utils/TestURIBuilder.java | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java index 1cc54ebce6..baf7122f34 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java @@ -493,7 +493,7 @@ public String toString() { private static String normalizePath(final String path) { String s = path; if (s == null) { - return null; + return "/"; } int n = 0; for (; n < s.length(); n++) { @@ -504,6 +504,9 @@ private static String normalizePath(final String path) { if (n > 1) { s = s.substring(n - 1); } + if (!s.startsWith("/")) { + s = "/" + s; + } return s; } diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java index 6ed9d7af96..6afc594220 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java @@ -292,4 +292,11 @@ private List createParameters() { return parameters; } + @Test + public void testMalformedPath() throws Exception { + final String path = "@notexample.com/mypath"; + final URI uri = new URIBuilder(path).setHost("example.com").build(); + Assert.assertEquals("example.com", uri.getHost()); + } + } From 7a4f0f728a875ca5694c9afedc88a426d1dbc543 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 21 Jan 2017 15:34:03 +0000 Subject: [PATCH 100/204] Removed obsolete script git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1779739 13f79535-47bb-0310-9956-ffa450edef68 --- jcip-annotations.py | 74 --------------------------------------------- 1 file changed, 74 deletions(-) delete mode 100644 jcip-annotations.py diff --git a/jcip-annotations.py b/jcip-annotations.py deleted file mode 100644 index 448e08c637..0000000000 --- a/jcip-annotations.py +++ /dev/null @@ -1,74 +0,0 @@ -#==================================================================== -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ==================================================================== -# -# This software consists of voluntary contributions made by many -# individuals on behalf of the Apache Software Foundation. For more -# information on the Apache Software Foundation, please see -# . -# - -import os -import re -import tempfile -import shutil - -ignore_pattern = re.compile('^(.svn|target|bin|classes)') -java_pattern = re.compile('^.*\.java') -annot_pattern = re.compile('import org\.apache\.http\.annotation\.') - -def process_dir(dir): - files = os.listdir(dir) - for file in files: - f = os.path.join(dir, file) - if os.path.isdir(f): - if not ignore_pattern.match(file): - process_dir(f) - else: - if java_pattern.match(file): - process_source(f) - -def process_source(filename): - tmp = tempfile.mkstemp() - tmpfd = tmp[0] - tmpfile = tmp[1] - try: - changed = False - dst = os.fdopen(tmpfd, 'w') - try: - src = open(filename) - try: - for line in src: - if annot_pattern.match(line): - changed = True - line = line.replace('import org.apache.http.annotation.', 'import net.jcip.annotations.') - dst.write(line) - finally: - src.close() - finally: - dst.close(); - - if changed: - shutil.move(tmpfile, filename) - else: - os.remove(tmpfile) - - except: - os.remove(tmpfile) - -process_dir('.') From 99bbc7755bb27a1124c87bd803c8675ecb680c64 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 21 Jan 2017 15:34:10 +0000 Subject: [PATCH 101/204] Updated release notes for HttpClient 4.5.3 release git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1779740 13f79535-47bb-0310-9956-ffa450edef68 --- NOTICE.txt | 2 +- RELEASE_NOTES.txt | 69 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index 91e5c40c4c..73c360ed1c 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Apache HttpComponents Client -Copyright 1999-2016 The Apache Software Foundation +Copyright 1999-2017 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 20d2e68d13..3f556223fc 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,15 +1,78 @@ Release 4.5.3 ------------------- -HttpClient 4.5.3 (GA) is a maintenance release that fixes a number of minor defects found since 4.5.2. +HttpClient 4.5.3 (GA) is a maintenance release that fixes a number of defects found since 4.5.2. Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- -* [HTTPCLIENT-1727] org.apache.http.impl.client.AbstractHttpClient#createClientConnectionManager Does not account for context class loader. - Contributed by Charles Allen +* [HTTPCLIENT-1803] Improved handling of malformed paths by URIBuilder. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1802] Do not attempt to match SSL host to subject CN if subject alternative name of any type are given. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1788] RFC 6265 policy must not reject cookies with paths that are no prefix of the uri path. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1792] SSLConnectionSocketFactory to throw SSLPeerUnverifiedException with a better error message + when hostname verification fails. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1779] [OSGi] support NTLM proxy authentication. + Contributed by Julian Sedding + +* [HTTPCLIENT-1773] [OSGi] HttpProxyConfigurationActivator does not unregister HttpClientBuilderFactory. + Contributed by Julian Sedding + +* [HTTPCLIENT-1771] improve OSGi webconsole display for org.apache.http.proxyconfigurator. + Contributed by Julian Sedding + +* [HTTPCLIENT-1770] OSGi metatype for org.apache.http.proxyconfigurator missing factoryPid. + Contributed by Julian Sedding + +* [HTTPCLIENT-1767] Null pointer dereference in EofSensorInputStream and ResponseEntityProxy. + Contributed by Peter Ansell + +* Support changing system default ProxySelector. + Contributed by Robin Stevens + +* All services registered in the OSGi service registry provide the whole bundle header dictionary as vendor + property value. + Contributed by Christoph Fiehe + +* [HTTPCLIENT-1750] OSGi support for CachingHttpClientBuilder. + Contributed by Justin Edelson + +* [HTTPCLIENT-1749] OSGi client builder to use weak references to track HttpClient instances. + Contributed by Justin Edelson + +* [HTTPCLIENT-1747] apply RequestConfig defaults when using HttpParams values in backward compatibility mode. + Contributed by Oleg Kalnichevski + +* Override LaxRedirectStrategy's INSTANCE field. + Contributed by Eric Wu + +* [HTTPCLIENT-1736] do not request cred delegation by default when using Kerberos auth. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1744] normalize hostname and certificate CN when matching to CN. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1732] SystemDefaultCredentialsProvider to take http.proxyHost and http.proxyPort system + properties into account. + Contributed by Oleg Kalnichevski + +* Revert "HTTPCLIENT-1712: SPNego schemes to take service scheme into account when generating auth token". + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1727] AbstractHttpClient#createClientConnectionManager does not account for context class loader. + Contributed by Charles Allen + +* [HTTPCLIENT-1726:] Copy the SNI fix from SSLConnectionSocketFactory to the deprecated SSLSocketFactory class. + Contributed by David Black Release 4.5.2 From ef95068aefba47dea805610d12afd13d59ad76e9 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 26 Jan 2017 09:53:49 +0000 Subject: [PATCH 102/204] Upgraded HttpClient version to 4.5.4-SNAPSHOT git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1780344 13f79535-47bb-0310-9956-ffa450edef68 --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 626a4e20b7..99fea1a319 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.3-SNAPSHOT + 4.5.4-SNAPSHOT fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 4dd8fc16b7..eda4286548 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.3-SNAPSHOT + 4.5.4-SNAPSHOT httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 06703d3ebd..7ac38ceac2 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.3-SNAPSHOT + 4.5.4-SNAPSHOT httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index e19af78b69..be33e8079f 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.3-SNAPSHOT + 4.5.4-SNAPSHOT httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 383ff60589..2977db2892 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.3-SNAPSHOT + 4.5.4-SNAPSHOT httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index df073cc044..ffe027490a 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.3-SNAPSHOT + 4.5.4-SNAPSHOT httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 979a427a3d..a3badfe94a 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.3-SNAPSHOT + 4.5.4-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 From 9c268589245f5111245ce3a293b9a15754142736 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 8 Feb 2017 19:37:31 +0000 Subject: [PATCH 103/204] HTTPCLIENT-1810: When path is null or '', URIBuilder.toString() return '' rather than '/'. Contributed by CuiBaosen git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1782238 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/client/utils/URIBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java index baf7122f34..974d34e5cb 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java @@ -37,6 +37,7 @@ import org.apache.http.NameValuePair; import org.apache.http.conn.util.InetAddressUtils; import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.TextUtils; /** * Builder for {@link URI} instances. @@ -492,8 +493,8 @@ public String toString() { private static String normalizePath(final String path) { String s = path; - if (s == null) { - return "/"; + if (TextUtils.isBlank(s)) { + return ""; } int n = 0; for (; n < s.length(); n++) { From 786371d9989980a839d1c6d018e5167f1f4de1a0 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 17 Feb 2017 09:03:50 +0000 Subject: [PATCH 104/204] [HTTPCLIENT-1816] Update Apache Commons Codec 1.9 to 1.10. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1783352 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 13 +++++++++++++ pom.xml | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 3f556223fc..7894934649 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,16 @@ +Release 4.5.4 +------------------- + +HttpClient 4.5.4 (GA) is a maintenance release that fixes a number of defects found since 4.5.3. + +Please note that as of 4.4 HttpClient requires Java 1.6 or newer. + +Changelog: +------------------- + +* [HTTPCLIENT-1816] Update Apache Commons Codec 1.9 to 1.10. + Contributed by Gary Gregory + Release 4.5.3 ------------------- diff --git a/pom.xml b/pom.xml index a3badfe94a..8d71f15c42 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 1.6 4.4.6 1.2 - 1.9 + 1.10 2.6.9 2.11.4 1.7.7 From 4438e47411b22fa31751c342910f2975161091bc Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 17 Feb 2017 09:09:48 +0000 Subject: [PATCH 105/204] Add missing EOL. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1783354 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 7894934649..5edbd006f9 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -11,6 +11,7 @@ Changelog: * [HTTPCLIENT-1816] Update Apache Commons Codec 1.9 to 1.10. Contributed by Gary Gregory + Release 4.5.3 ------------------- From 7ff6b6c438cf3d4190a3d40b542c20e4774b8e25 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 20 Feb 2017 22:40:41 +0000 Subject: [PATCH 106/204] [HTTPCLIENT-1817] Add a "Trust All" TrustStrategy implementation. --- RELEASE_NOTES.txt | 3 + .../http/conn/ssl/TrustAllStrategy.java | 48 +++++++++++ .../apache/http/conn/ssl/TrustStrategy.java | 8 +- .../http/conn/ssl/TestSSLSocketFactory.java | 85 ++++++++++++++----- 4 files changed, 119 insertions(+), 25 deletions(-) create mode 100644 httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 5edbd006f9..0e2ae4e93e 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -8,6 +8,9 @@ Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- +* [HTTPCLIENT-1817] Add a "Trust All" TrustStrategy implementation. + Contributed by Gary Gregory + * [HTTPCLIENT-1816] Update Apache Commons Codec 1.9 to 1.10. Contributed by Gary Gregory diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java b/httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java new file mode 100644 index 0000000000..d492404e08 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java @@ -0,0 +1,48 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.conn.ssl; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * A trust strategy that accepts all certificates as trusted. Verification of + * all other certificates is done by the trust manager configured in the SSL + * context. + * + * @since 4.5.4 + */ +public class TrustAllStrategy implements TrustStrategy { + + public static final TrustAllStrategy INSTANCE = new TrustAllStrategy(); + + @Override + public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { + return true; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/TrustStrategy.java b/httpclient/src/main/java/org/apache/http/conn/ssl/TrustStrategy.java index 53a8091d4c..aad4dfe477 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/TrustStrategy.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/TrustStrategy.java @@ -27,12 +27,14 @@ package org.apache.http.conn.ssl; /** - * A strategy to establish trustworthiness of certificates without consulting the trust manager - * configured in the actual SSL context. This interface can be used to override the standard - * JSSE certificate verification process. + * A strategy to establish trustworthiness of certificates without consulting + * the trust manager configured in the actual SSL context. This interface can be + * used to override the standard JSSE certificate verification process. * * @since 4.1 */ public interface TrustStrategy extends org.apache.http.ssl.TrustStrategy { + // Empty! Inherits from org.apache.http.ssl.TrustStrategy. + } diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java b/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java index 8272ac40f7..094135672f 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java @@ -30,6 +30,9 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.concurrent.TimeUnit; @@ -86,10 +89,12 @@ public boolean isFired() { @Test public void testBasicSSL() throws Exception { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); @@ -99,7 +104,8 @@ public void testBasicSSL() throws Exception { final Socket socket = socketFactory.createSocket(context); final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); - final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, + context); try { final SSLSession sslsession = sslSocket.getSession(); @@ -112,10 +118,12 @@ public void testBasicSSL() throws Exception { @Test public void testBasicDefaultHostnameVerifier() throws Exception { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); @@ -124,7 +132,8 @@ public void testBasicDefaultHostnameVerifier() throws Exception { final Socket socket = socketFactory.createSocket(context); final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); - final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, + context); try { final SSLSession sslsession = sslSocket.getSession(); @@ -136,10 +145,12 @@ public void testBasicDefaultHostnameVerifier() throws Exception { @Test public void testClientAuthSSL() throws Exception { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); @@ -149,7 +160,8 @@ public void testClientAuthSSL() throws Exception { final Socket socket = socketFactory.createSocket(context); final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); - final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, + context); try { final SSLSession sslsession = sslSocket.getSession(); @@ -160,8 +172,9 @@ public void testClientAuthSSL() throws Exception { } } - @Test(expected=IOException.class) + @Test(expected = IOException.class) public void testClientAuthSSLFailure() throws Exception { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) @@ -174,6 +187,7 @@ public void initialize(final SSLServerSocket socket) throws SSLException { }) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); @@ -183,7 +197,8 @@ public void initialize(final SSLServerSocket socket) throws SSLException { final Socket socket = socketFactory.createSocket(context); final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); - final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, + context); try { final SSLSession sslsession = sslSocket.getSession(); @@ -194,12 +209,14 @@ public void initialize(final SSLServerSocket socket) throws SSLException { } } - @Test(expected=SSLException.class) + @Test(expected = SSLException.class) public void testSSLTrustVerification() throws Exception { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); @@ -212,45 +229,65 @@ public void testSSLTrustVerification() throws Exception { final Socket socket = socketFactory.createSocket(context); final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); - final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, + context); sslSocket.close(); } @Test - public void testSSLTrustVerificationOverride() throws Exception { + public void testSSLTrustVerificationOverrideWithCustsom() throws Exception { + final TrustStrategy trustStrategy = new TrustStrategy() { + + @Override + public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { + return chain.length == 1; + } + + }; + testSSLTrustVerificationOverride(trustStrategy); + } + + @Test + public void testSSLTrustVerificationOverrideWithTrustSelfSignedStrategy() throws Exception { + testSSLTrustVerificationOverride(TrustSelfSignedStrategy.INSTANCE); + } + + @Test + public void testSSLTrustVerificationOverrideWithTrustAllStrategy() throws Exception { + testSSLTrustVerificationOverride(TrustAllStrategy.INSTANCE); + } + + private void testSSLTrustVerificationOverride(final TrustStrategy trustStrategy) + throws Exception, IOException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); - final TrustStrategy trustStrategy = new TrustStrategy() { - - @Override - public boolean isTrusted( - final X509Certificate[] chain, final String authType) throws CertificateException { - return chain.length == 1; - } - - }; + // @formatter:off final SSLContext sslcontext = SSLContexts.custom() .loadTrustMaterial(null, trustStrategy) .build(); - final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - sslcontext, + // @formatter:on + final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE); final Socket socket = socketFactory.createSocket(context); final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); - final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, + context); sslSocket.close(); } @Test public void testTLSOnly() throws Exception { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) @@ -263,6 +300,7 @@ public void initialize(final SSLServerSocket socket) throws SSLException { }) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); @@ -271,13 +309,15 @@ public void initialize(final SSLServerSocket socket) throws SSLException { final Socket socket = socketFactory.createSocket(context); final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); - final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final SSLSocket sslSocket = (SSLSocket) socketFactory.connectSocket(0, socket, target, remoteAddress, null, + context); final SSLSession sslsession = sslSocket.getSession(); Assert.assertNotNull(sslsession); } - @Test(expected=IOException.class) + @Test(expected = IOException.class) public void testSSLDisabledByDefault() throws Exception { + // @formatter:off this.server = ServerBootstrap.bootstrap() .setServerInfo(LocalServerTestBase.ORIGIN) .setSslContext(SSLTestContexts.createServerSSLContext()) @@ -290,6 +330,7 @@ public void initialize(final SSLServerSocket socket) throws SSLException { }) .create(); + // @formatter:on this.server.start(); final HttpContext context = new BasicHttpContext(); From a2a581eba12889f9b5a7ad36e698f3c3c5188bc6 Mon Sep 17 00:00:00 2001 From: Karl Wright Date: Fri, 17 Mar 2017 16:04:02 +0000 Subject: [PATCH 107/204] Fix for HTTPCLIENT-1833 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1787433 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 3 +++ .../http/impl/auth/win/WindowsNegotiateScheme.java | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 0e2ae4e93e..95ceac3cd8 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -8,6 +8,9 @@ Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- +* [HTTPCLIENT-1833] Fix Windows Negotiate-NTLM handling of proxies. + Contributed by Roman Stoffel + * [HTTPCLIENT-1817] Add a "Trust All" TrustStrategy implementation. Contributed by Gary Gregory diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java index 7e8b86612e..b07c75ec50 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java @@ -241,10 +241,18 @@ private String getServicePrincipalName(final HttpContext context) { final String spn; if (this.servicePrincipalName != null) { spn = this.servicePrincipalName; + } else if(isProxy()){ + final HttpClientContext clientContext = HttpClientContext.adapt(context); + final RouteInfo route = clientContext.getHttpRoute(); + if (route != null) { + spn = "HTTP/" + route.getProxyHost().getHostName(); + } else { + // Should not happen + spn = null; + } } else { final HttpClientContext clientContext = HttpClientContext.adapt(context); - final HttpHost target = clientContext.getTargetHost(); - if (target != null) { + final HttpHost target = clientContext.getTargetHost(); if (target != null) { spn = "HTTP/" + target.getHostName(); } else { final RouteInfo route = clientContext.getHttpRoute(); From 44f8924b58fe8860d5ea1be52f0a4363d4f640cc Mon Sep 17 00:00:00 2001 From: Karl Wright Date: Thu, 16 Mar 2017 11:06:46 +0000 Subject: [PATCH 108/204] HTTPCLIENT-1834: NTLN auth refactoring; support for MS CredSsp auth Contributed by Radovan Semancik and Karl Wright --- .../impl/auth/win/WindowsNegotiateScheme.java | 3 +- .../http/client/config/AuthSchemes.java | 5 + .../apache/http/impl/auth/CredSspScheme.java | 1126 +++++++++++++++++ .../http/impl/auth/CredSspSchemeFactory.java | 44 + .../org/apache/http/impl/auth/DebugUtil.java | 96 ++ .../apache/http/impl/auth/NTLMEngineImpl.java | 843 +++++++++--- .../client/AuthenticationStrategyImpl.java | 2 +- .../http/impl/auth/TestNTLMEngineImpl.java | 87 +- 8 files changed, 2005 insertions(+), 201 deletions(-) create mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java create mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java create mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java index b07c75ec50..333458bd5e 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java @@ -252,7 +252,8 @@ private String getServicePrincipalName(final HttpContext context) { } } else { final HttpClientContext clientContext = HttpClientContext.adapt(context); - final HttpHost target = clientContext.getTargetHost(); if (target != null) { + final HttpHost target = clientContext.getTargetHost(); + if (target != null) { spn = "HTTP/" + target.getHostName(); } else { final RouteInfo route = clientContext.getHttpRoute(); diff --git a/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java b/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java index da7e26881c..f3a0e1baf3 100644 --- a/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java +++ b/httpclient/src/main/java/org/apache/http/client/config/AuthSchemes.java @@ -65,6 +65,11 @@ public final class AuthSchemes { */ public static final String KERBEROS = "Kerberos"; + /** + * CredSSP authentication scheme defined in [MS-CSSP]. + */ + public static final String CREDSSP = "CredSSP"; + private AuthSchemes() { } diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java new file mode 100644 index 0000000000..f8db658c98 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java @@ -0,0 +1,1126 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.auth; + + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.Consts; +import org.apache.http.Header; +import org.apache.http.HttpRequest; +import org.apache.http.auth.AUTH; +import org.apache.http.auth.AuthenticationException; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.InvalidCredentialsException; +import org.apache.http.auth.MalformedChallengeException; +import org.apache.http.auth.NTCredentials; +import org.apache.http.message.BufferedHeader; +import org.apache.http.protocol.HttpContext; +import org.apache.http.ssl.SSLContexts; +import org.apache.http.util.CharArrayBuffer; +import org.apache.http.util.CharsetUtils; + +/** + *

+ * Client implementation of the CredSSP protocol specified in [MS-CSSP]. + *

+ *

+ * Note: This is implementation is NOT GSS based. It should be. But there is no Java NTLM + * implementation as GSS module. Maybe the NTLMEngine can be converted to GSS and then this + * can be also switched to GSS. In fact it only works in CredSSP+NTLM case. + *

+ *

+ * Based on [MS-CSSP]: Credential Security Support Provider (CredSSP) Protocol (Revision 13.0, 7/14/2016). + * The implementation was inspired by Python CredSSP and NTLM implementation by Jordan Borean. + *

+ */ +public class CredSspScheme extends AuthSchemeBase +{ + private static final Charset UNICODE_LITTLE_UNMARKED = CharsetUtils.lookup( "UnicodeLittleUnmarked" ); + public static final String SCHEME_NAME = "CredSSP"; + + private final Log log = LogFactory.getLog( CredSspScheme.class ); + + enum State + { + // Nothing sent, nothing received + UNINITIATED, + + // We are handshaking. Several messages are exchanged in this state + TLS_HANDSHAKE, + + // TLS handshake finished. Channel established + TLS_HANDSHAKE_FINISHED, + + // NTLM NEGOTIATE message sent (strictly speaking this should be SPNEGO) + NEGO_TOKEN_SENT, + + // NTLM CHALLENGE message received (strictly speaking this should be SPNEGO) + NEGO_TOKEN_RECEIVED, + + // NTLM AUTHENTICATE message sent together with a server public key + PUB_KEY_AUTH_SENT, + + // Server public key authentication message received + PUB_KEY_AUTH_RECEIVED, + + // Credentials message sent. Protocol exchange finished. + CREDENTIALS_SENT; + } + + private State state; + private SSLEngine sslEngine; + private NTLMEngineImpl.Type1Message type1Message; + private NTLMEngineImpl.Type2Message type2Message; + private NTLMEngineImpl.Type3Message type3Message; + private CredSspTsRequest lastReceivedTsRequest; + private NTLMEngineImpl.Handle ntlmOutgoingHandle; + private NTLMEngineImpl.Handle ntlmIncomingHandle; + private byte[] peerPublicKey; + + + public CredSspScheme() { + state = State.UNINITIATED; + } + + + @Override + public String getSchemeName() + { + return SCHEME_NAME; + } + + + @Override + public String getParameter( final String name ) + { + return null; + } + + + @Override + public String getRealm() + { + return null; + } + + + @Override + public boolean isConnectionBased() + { + return true; + } + + + private SSLEngine getSSLEngine() + { + if ( sslEngine == null ) + { + sslEngine = createSSLEngine(); + } + return sslEngine; + } + + + private SSLEngine createSSLEngine() + { + SSLContext sslContext; + try + { + sslContext = SSLContexts.custom().build(); + } + catch ( NoSuchAlgorithmException e ) + { + throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); + } + catch ( KeyManagementException e ) + { + throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); + } + + final X509TrustManager tm = new X509TrustManager() + { + + @Override + public void checkClientTrusted( final X509Certificate[] chain, final String authType ) + throws CertificateException + { + // Nothing to do. + } + + + @Override + public void checkServerTrusted( final X509Certificate[] chain, final String authType ) + throws CertificateException + { + // Nothing to do, accept all. CredSSP server is using its own certificate without any + // binding to the PKI trust chains. The public key is verified as part of the CredSSP + // protocol exchange. + } + + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return null; + } + + }; + try + { + sslContext.init( null, new TrustManager[] + { tm }, null ); + } + catch ( KeyManagementException e ) + { + throw new RuntimeException( "SSL Context initialization error: " + e.getMessage(), e ); + } + final SSLEngine sslEngine = sslContext.createSSLEngine(); + sslEngine.setUseClientMode( true ); + return sslEngine; + } + + + @Override + protected void parseChallenge( final CharArrayBuffer buffer, final int beginIndex, final int endIndex ) + throws MalformedChallengeException + { + final String inputString = buffer.substringTrimmed( beginIndex, endIndex ); + + if ( inputString.isEmpty() ) + { + if ( state == State.UNINITIATED ) + { + // This is OK, just send out first message. That should start TLS handshake + } + else + { + final String msg = "Received unexpected empty input in state " + state; + log.error( msg ); + throw new MalformedChallengeException( msg ); + } + } + + if ( state == State.TLS_HANDSHAKE ) + { + unwrapHandshake( inputString ); + if ( getSSLEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ) + { + log.trace( "TLS handshake finished" ); + state = State.TLS_HANDSHAKE_FINISHED; + } + } + + if ( state == State.NEGO_TOKEN_SENT ) + { + final ByteBuffer buf = unwrap( inputString ); + state = State.NEGO_TOKEN_RECEIVED; + lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); + } + + if ( state == State.PUB_KEY_AUTH_SENT ) + { + final ByteBuffer buf = unwrap( inputString ); + state = State.PUB_KEY_AUTH_RECEIVED; + lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); + } + } + + + @Override + @Deprecated + public Header authenticate( + final Credentials credentials, + final HttpRequest request ) throws AuthenticationException + { + return authenticate( credentials, request, null ); + } + + + @Override + public Header authenticate( + final Credentials credentials, + final HttpRequest request, + final HttpContext context ) throws AuthenticationException + { + NTCredentials ntcredentials = null; + try + { + ntcredentials = ( NTCredentials ) credentials; + } + catch ( final ClassCastException e ) + { + throw new InvalidCredentialsException( + "Credentials cannot be used for CredSSP authentication: " + + credentials.getClass().getName() ); + } + + String outputString = null; + + if ( state == State.UNINITIATED ) + { + beginTlsHandshake(); + outputString = wrapHandshake(); + state = State.TLS_HANDSHAKE; + + } + else if ( state == State.TLS_HANDSHAKE ) + { + outputString = wrapHandshake(); + + } + else if ( state == State.TLS_HANDSHAKE_FINISHED ) + { + + final int ntlmFlags = getNtlmFlags(); + final ByteBuffer buf = allocateOutBuffer(); + type1Message = new NTLMEngineImpl.Type1Message( + ntcredentials.getDomain(), ntcredentials.getWorkstation(), ntlmFlags); + final byte[] ntlmNegoMessageEncoded = type1Message.getBytes(); + final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmNegoMessageEncoded ); + req.encode( buf ); + buf.flip(); + outputString = wrap( buf ); + state = State.NEGO_TOKEN_SENT; + + } + else if ( state == State.NEGO_TOKEN_RECEIVED ) + { + final ByteBuffer buf = allocateOutBuffer(); + type2Message = new NTLMEngineImpl.Type2Message( + lastReceivedTsRequest.getNegoToken()); + + final Certificate peerServerCertificate = getPeerServerCertificate(); + + type3Message = new NTLMEngineImpl.Type3Message( + ntcredentials.getDomain(), + ntcredentials.getWorkstation(), + ntcredentials.getUserName(), + ntcredentials.getPassword(), + type2Message.getChallenge(), + type2Message.getFlags(), + type2Message.getTarget(), + type2Message.getTargetInfo(), + peerServerCertificate, + type1Message.getBytes(), + type2Message.getBytes()); + + final byte[] ntlmAuthenticateMessageEncoded = type3Message.getBytes(); + + final byte[] exportedSessionKey = type3Message.getExportedSessionKey(); + + ntlmOutgoingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.CLIENT, true); + ntlmIncomingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.SERVER, true); + + final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmAuthenticateMessageEncoded ); + peerPublicKey = getSubjectPublicKeyDer( peerServerCertificate.getPublicKey() ); + final byte[] pubKeyAuth = createPubKeyAuth(); + req.setPubKeyAuth( pubKeyAuth ); + + req.encode( buf ); + buf.flip(); + outputString = wrap( buf ); + state = State.PUB_KEY_AUTH_SENT; + + } + else if ( state == State.PUB_KEY_AUTH_RECEIVED ) + { + verifyPubKeyAuthResponse( lastReceivedTsRequest.getPubKeyAuth() ); + final byte[] authInfo = createAuthInfo( ntcredentials ); + final CredSspTsRequest req = CredSspTsRequest.createAuthInfo( authInfo ); + + final ByteBuffer buf = allocateOutBuffer(); + req.encode( buf ); + buf.flip(); + outputString = wrap( buf ); + state = State.CREDENTIALS_SENT; + } + else + { + throw new AuthenticationException( "Wrong state " + state ); + } + final CharArrayBuffer buffer = new CharArrayBuffer( 32 ); + if ( isProxy() ) + { + buffer.append( AUTH.PROXY_AUTH_RESP ); + } + else + { + buffer.append( AUTH.WWW_AUTH_RESP ); + } + buffer.append( ": CredSSP " ); + buffer.append( outputString ); + return new BufferedHeader( buffer ); + } + + + private int getNtlmFlags() + { + return NTLMEngineImpl.FLAG_REQUEST_OEM_ENCODING | + NTLMEngineImpl.FLAG_REQUEST_SIGN | + NTLMEngineImpl.FLAG_REQUEST_SEAL | + NTLMEngineImpl.FLAG_DOMAIN_PRESENT | + NTLMEngineImpl.FLAG_REQUEST_ALWAYS_SIGN | + NTLMEngineImpl.FLAG_REQUEST_NTLM2_SESSION | + NTLMEngineImpl.FLAG_TARGETINFO_PRESENT | + NTLMEngineImpl.FLAG_REQUEST_VERSION | + NTLMEngineImpl.FLAG_REQUEST_128BIT_KEY_EXCH | + NTLMEngineImpl.FLAG_REQUEST_EXPLICIT_KEY_EXCH | + NTLMEngineImpl.FLAG_REQUEST_56BIT_ENCRYPTION; + } + + + private Certificate getPeerServerCertificate() throws AuthenticationException + { + Certificate[] peerCertificates; + try + { + peerCertificates = sslEngine.getSession().getPeerCertificates(); + } + catch ( SSLPeerUnverifiedException e ) + { + throw new AuthenticationException( e.getMessage(), e ); + } + for ( Certificate peerCertificate : peerCertificates ) + { + if ( !( peerCertificate instanceof X509Certificate ) ) + { + continue; + } + final X509Certificate peerX509Cerificate = ( X509Certificate ) peerCertificate; + if ( peerX509Cerificate.getBasicConstraints() != -1 ) + { + continue; + } + return peerX509Cerificate; + } + return null; + } + + + private byte[] createPubKeyAuth() throws AuthenticationException + { + return ntlmOutgoingHandle.signAndEncryptMessage( peerPublicKey ); + } + + + private void verifyPubKeyAuthResponse( final byte[] pubKeyAuthResponse ) throws AuthenticationException + { + final byte[] pubKeyReceived = ntlmIncomingHandle.decryptAndVerifySignedMessage( pubKeyAuthResponse ); + + // assert: pubKeyReceived = peerPublicKey + 1 + // The following algorithm is a bit simplified. But due to the ASN.1 encoding the first byte + // of the public key will be 0x30 we can pretty much rely on a fact that there will be no carry + if ( peerPublicKey.length != pubKeyReceived.length ) + { + throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); + } + if ( ( peerPublicKey[0] + 1 ) != pubKeyReceived[0] ) + { + throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); + } + for ( int i = 1; i < peerPublicKey.length; i++ ) + { + if ( peerPublicKey[i] != pubKeyReceived[i] ) + { + throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); + } + } + log.trace( "Received public key response is valid" ); + } + + + private byte[] createAuthInfo( final NTCredentials ntcredentials ) throws AuthenticationException + { + + final byte[] domainBytes = encodeUnicode( ntcredentials.getDomain() ); + final byte[] domainOctetStringBytesLengthBytes = encodeLength( domainBytes.length ); + final int domainNameLength = 1 + domainOctetStringBytesLengthBytes.length + domainBytes.length; + final byte[] domainNameLengthBytes = encodeLength( domainNameLength ); + + final byte[] usernameBytes = encodeUnicode( ntcredentials.getUserName() ); + final byte[] usernameOctetStringBytesLengthBytes = encodeLength( usernameBytes.length ); + final int userNameLength = 1 + usernameOctetStringBytesLengthBytes.length + usernameBytes.length; + final byte[] userNameLengthBytes = encodeLength( userNameLength ); + + final byte[] passwordBytes = encodeUnicode( ntcredentials.getPassword() ); + final byte[] passwordOctetStringBytesLengthBytes = encodeLength( passwordBytes.length ); + final int passwordLength = 1 + passwordOctetStringBytesLengthBytes.length + passwordBytes.length; + final byte[] passwordLengthBytes = encodeLength( passwordLength ); + + final int tsPasswordLength = 1 + domainNameLengthBytes.length + domainNameLength + + 1 + userNameLengthBytes.length + userNameLength + + 1 + passwordLengthBytes.length + passwordLength; + final byte[] tsPasswordLengthBytes = encodeLength( tsPasswordLength ); + final int credentialsOctetStringLength = 1 + tsPasswordLengthBytes.length + tsPasswordLength; + final byte[] credentialsOctetStringLengthBytes = encodeLength( credentialsOctetStringLength ); + final int credentialsLength = 1 + credentialsOctetStringLengthBytes.length + credentialsOctetStringLength; + final byte[] credentialsLengthBytes = encodeLength( credentialsLength ); + final int tsCredentialsLength = 5 + 1 + credentialsLengthBytes.length + credentialsLength; + final byte[] tsCredentialsLengthBytes = encodeLength( tsCredentialsLength ); + + final ByteBuffer buf = ByteBuffer.allocate( 1 + tsCredentialsLengthBytes.length + tsCredentialsLength ); + + // TSCredentials structure [MS-CSSP] section 2.2.1.2 + buf.put( ( byte ) 0x30 ); // seq + buf.put( tsCredentialsLengthBytes ); + + buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // credType tag [0] + buf.put( ( byte ) 3 ); // credType length + buf.put( ( byte ) 0x02 ); // type: INTEGER + buf.put( ( byte ) 1 ); // credType inner length + buf.put( ( byte ) 1 ); // credType value: 1 (password) + + buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // credentials tag [1] + buf.put( credentialsLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( credentialsOctetStringLengthBytes ); + + // TSPasswordCreds structure [MS-CSSP] section 2.2.1.2.1 + buf.put( ( byte ) 0x30 ); // seq + buf.put( tsPasswordLengthBytes ); + + buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // domainName tag [0] + buf.put( domainNameLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( domainOctetStringBytesLengthBytes ); + buf.put( domainBytes ); + + buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // userName tag [1] + buf.put( userNameLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( usernameOctetStringBytesLengthBytes ); + buf.put( usernameBytes ); + + buf.put( ( byte ) ( 0x02 | 0xa0 ) ); // password tag [2] + buf.put( passwordLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( passwordOctetStringBytesLengthBytes ); + buf.put( passwordBytes ); + + final byte[] authInfo = buf.array(); + try + { + return ntlmOutgoingHandle.signAndEncryptMessage( authInfo ); + } + catch ( NTLMEngineException e ) + { + throw new AuthenticationException( e.getMessage(), e ); + } + } + + private final static byte[] EMPTYBUFFER = new byte[0]; + + private byte[] encodeUnicode( final String string ) + { + if (string == null) { + return EMPTYBUFFER; + } + return string.getBytes( UNICODE_LITTLE_UNMARKED ); + } + + + private byte[] getSubjectPublicKeyDer( final PublicKey publicKey ) throws AuthenticationException + { + // The publicKey.getEncoded() returns encoded SubjectPublicKeyInfo structure. But the CredSSP expects + // SubjectPublicKey subfield. I have found no easy way how to get just the SubjectPublicKey from + // java.security libraries. So let's use a primitive way and parse it out from the DER. + + try + { + final byte[] encodedPubKeyInfo = publicKey.getEncoded(); + + final ByteBuffer buf = ByteBuffer.wrap( encodedPubKeyInfo ); + getByteAndAssert( buf, 0x30, "initial sequence" ); + parseLength( buf ); + getByteAndAssert( buf, 0x30, "AlgorithmIdentifier sequence" ); + final int algIdSeqLength = parseLength( buf ); + buf.position( buf.position() + algIdSeqLength ); + getByteAndAssert( buf, 0x03, "subjectPublicKey type" ); + int subjectPublicKeyLegth = parseLength( buf ); + // There may be leading padding byte ... or whatever that is. Skip that. + final byte b = buf.get(); + if ( b == 0 ) + { + subjectPublicKeyLegth--; + } + else + { + buf.position( buf.position() - 1 ); + } + final byte[] subjectPublicKey = new byte[subjectPublicKeyLegth]; + buf.get( subjectPublicKey ); + return subjectPublicKey; + } + catch ( MalformedChallengeException e ) + { + throw new AuthenticationException( e.getMessage(), e ); + } + } + + + private void beginTlsHandshake() throws AuthenticationException + { + try + { + getSSLEngine().beginHandshake(); + } + catch ( SSLException e ) + { + throw new AuthenticationException( "SSL Engine error: " + e.getMessage(), e ); + } + } + + + private ByteBuffer allocateOutBuffer() + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + return ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); + } + + + private String wrapHandshake() throws AuthenticationException + { + final ByteBuffer src = allocateOutBuffer(); + src.flip(); + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + // Needs to be twice the size as there may be two wraps during handshake. + // Primitive and inefficient solution, but it works. + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() * 2 ); + while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ) + { + wrap( src, dst ); + } + dst.flip(); + return encodeBase64( dst ); + } + + + private String wrap( final ByteBuffer src ) throws AuthenticationException + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() ); + wrap( src, dst ); + dst.flip(); + return encodeBase64( dst ); + } + + + private void wrap( final ByteBuffer src, final ByteBuffer dst ) throws AuthenticationException + { + final SSLEngine sslEngine = getSSLEngine(); + try + { + final SSLEngineResult engineResult = sslEngine.wrap( src, dst ); + if ( engineResult.getStatus() != Status.OK ) + { + throw new AuthenticationException( "SSL Engine error status: " + engineResult.getStatus() ); + } + } + catch ( SSLException e ) + { + throw new AuthenticationException( "SSL Engine wrap error: " + e.getMessage(), e ); + } + } + + + private void unwrapHandshake( final String inputString ) throws MalformedChallengeException + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + final ByteBuffer src = decodeBase64( inputString ); + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); + while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) + { + unwrap( src, dst ); + } + } + + + private ByteBuffer unwrap( final String inputString ) throws MalformedChallengeException + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + final ByteBuffer src = decodeBase64( inputString ); + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); + unwrap( src, dst ); + dst.flip(); + return dst; + } + + + private void unwrap( final ByteBuffer src, final ByteBuffer dst ) throws MalformedChallengeException + { + + try + { + final SSLEngineResult engineResult = sslEngine.unwrap( src, dst ); + if ( engineResult.getStatus() != Status.OK ) + { + throw new MalformedChallengeException( "SSL Engine error status: " + engineResult.getStatus() ); + } + + if ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) + { + final Runnable task = sslEngine.getDelegatedTask(); + task.run(); + } + + } + catch ( SSLException e ) + { + throw new MalformedChallengeException( "SSL Engine unwrap error: " + e.getMessage(), e ); + } + } + + + private String encodeBase64( final ByteBuffer buffer ) + { + final int limit = buffer.limit(); + final byte[] bytes = new byte[limit]; + buffer.get( bytes ); + return new String(Base64.encodeBase64(bytes), Consts.ASCII); + } + + + private ByteBuffer decodeBase64( final String inputString ) + { + final byte[] inputBytes = Base64.decodeBase64(inputString.getBytes(Consts.ASCII)); + final ByteBuffer buffer = ByteBuffer.wrap( inputBytes ); + return buffer; + } + + + @Override + public boolean isComplete() + { + return state == State.CREDENTIALS_SENT; + } + + /** + * Implementation of the TsRequest structure used in CredSSP protocol. + * It is specified in [MS-CPPS] section 2.2.1. + */ + static class CredSspTsRequest + { + + private static final int VERSION = 3; + + private byte[] negoToken; + private byte[] authInfo; + private byte[] pubKeyAuth; + + + protected CredSspTsRequest() + { + super(); + } + + + public static CredSspTsRequest createNegoToken( final byte[] negoToken ) + { + final CredSspTsRequest req = new CredSspTsRequest(); + req.negoToken = negoToken; + return req; + } + + + public static CredSspTsRequest createAuthInfo( final byte[] authInfo ) + { + final CredSspTsRequest req = new CredSspTsRequest(); + req.authInfo = authInfo; + return req; + } + + + public static CredSspTsRequest createDecoded( final ByteBuffer buf ) throws MalformedChallengeException + { + final CredSspTsRequest req = new CredSspTsRequest(); + req.decode( buf ); + return req; + } + + + public byte[] getNegoToken() + { + return negoToken; + } + + + public void setNegoToken( final byte[] negoToken ) + { + this.negoToken = negoToken; + } + + + public byte[] getAuthInfo() + { + return authInfo; + } + + + public void setAuthInfo( final byte[] authInfo ) + { + this.authInfo = authInfo; + } + + + public byte[] getPubKeyAuth() + { + return pubKeyAuth; + } + + + public void setPubKeyAuth( final byte[] pubKeyAuth ) + { + this.pubKeyAuth = pubKeyAuth; + } + + + public void decode( final ByteBuffer buf ) throws MalformedChallengeException + { + negoToken = null; + authInfo = null; + pubKeyAuth = null; + + getByteAndAssert( buf, 0x30, "initial sequence" ); + parseLength( buf ); + + while ( buf.hasRemaining() ) + { + final int contentTag = getAndAssertContentSpecificTag( buf, "content tag" ); + parseLength( buf ); + switch ( contentTag ) + { + case 0: + processVersion( buf ); + break; + case 1: + parseNegoTokens( buf ); + break; + case 2: + parseAuthInfo( buf ); + break; + case 3: + parsePubKeyAuth( buf ); + break; + case 4: + processErrorCode( buf ); + break; + default: + parseError( buf, "unexpected content tag " + contentTag ); + } + } + } + + + private void processVersion( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x02, "version type" ); + getLengthAndAssert( buf, 1, "version length" ); + getByteAndAssert( buf, VERSION, "wrong protocol version" ); + } + + + private void parseNegoTokens( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x30, "negoTokens sequence" ); + parseLength( buf ); + // I have seen both 0x30LL encoding and 0x30LL0x30LL encoding. Accept both. + byte bufByte = buf.get(); + if ( bufByte == 0x30 ) + { + parseLength( buf ); + bufByte = buf.get(); + } + if ( ( bufByte & 0xff ) != 0xa0 ) + { + parseError( buf, "negoTokens: wrong content-specific tag " + String.format( "%02X", bufByte ) ); + } + parseLength( buf ); + getByteAndAssert( buf, 0x04, "negoToken type" ); + + final int tokenLength = parseLength( buf ); + negoToken = new byte[tokenLength]; + buf.get( negoToken ); + } + + + private void parseAuthInfo( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x04, "authInfo type" ); + final int length = parseLength( buf ); + authInfo = new byte[length]; + buf.get( authInfo ); + } + + + private void parsePubKeyAuth( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x04, "pubKeyAuth type" ); + final int length = parseLength( buf ); + pubKeyAuth = new byte[length]; + buf.get( pubKeyAuth ); + } + + + private void processErrorCode( final ByteBuffer buf ) throws MalformedChallengeException + { + getLengthAndAssert( buf, 3, "error code length" ); + getByteAndAssert( buf, 0x02, "error code type" ); + getLengthAndAssert( buf, 1, "error code length" ); + final byte errorCode = buf.get(); + parseError( buf, "Error code " + errorCode ); + } + + + public void encode( final ByteBuffer buf ) + { + final ByteBuffer inner = ByteBuffer.allocate( buf.capacity() ); + + // version tag [0] + inner.put( ( byte ) ( 0x00 | 0xa0 ) ); + inner.put( ( byte ) 3 ); // length + + inner.put( ( byte ) ( 0x02 ) ); // INTEGER tag + inner.put( ( byte ) 1 ); // length + inner.put( ( byte ) VERSION ); // value + + if ( negoToken != null ) + { + int len = negoToken.length; + final byte[] negoTokenLengthBytes = encodeLength( len ); + len += 1 + negoTokenLengthBytes.length; + final byte[] negoTokenLength1Bytes = encodeLength( len ); + len += 1 + negoTokenLength1Bytes.length; + final byte[] negoTokenLength2Bytes = encodeLength( len ); + len += 1 + negoTokenLength2Bytes.length; + final byte[] negoTokenLength3Bytes = encodeLength( len ); + len += 1 + negoTokenLength3Bytes.length; + final byte[] negoTokenLength4Bytes = encodeLength( len ); + + inner.put( ( byte ) ( 0x01 | 0xa0 ) ); // negoData tag [1] + inner.put( negoTokenLength4Bytes ); // length + + inner.put( ( byte ) ( 0x30 ) ); // SEQUENCE tag + inner.put( negoTokenLength3Bytes ); // length + + inner.put( ( byte ) ( 0x30 ) ); // .. of SEQUENCE tag + inner.put( negoTokenLength2Bytes ); // length + + inner.put( ( byte ) ( 0x00 | 0xa0 ) ); // negoToken tag [0] + inner.put( negoTokenLength1Bytes ); // length + + inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag + inner.put( negoTokenLengthBytes ); // length + + inner.put( negoToken ); + } + + if ( authInfo != null ) + { + final byte[] authInfoEncodedLength = encodeLength( authInfo.length ); + + inner.put( ( byte ) ( 0x02 | 0xa0 ) ); // authInfo tag [2] + inner.put( encodeLength( 1 + authInfoEncodedLength.length + authInfo.length ) ); // length + + inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag + inner.put( authInfoEncodedLength ); + inner.put( authInfo ); + } + + if ( pubKeyAuth != null ) + { + final byte[] pubKeyAuthEncodedLength = encodeLength( pubKeyAuth.length ); + + inner.put( ( byte ) ( 0x03 | 0xa0 ) ); // pubKeyAuth tag [3] + inner.put( encodeLength( 1 + pubKeyAuthEncodedLength.length + pubKeyAuth.length ) ); // length + + inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag + inner.put( pubKeyAuthEncodedLength ); + inner.put( pubKeyAuth ); + } + + inner.flip(); + + // SEQUENCE tag + buf.put( ( byte ) ( 0x10 | 0x20 ) ); + buf.put( encodeLength( inner.limit() ) ); + buf.put( inner ); + } + + + public String debugDump() + { + final StringBuilder sb = new StringBuilder( "TsRequest\n" ); + sb.append( " negoToken:\n" ); + sb.append( " " ); + DebugUtil.dump( sb, negoToken ); + sb.append( "\n" ); + sb.append( " authInfo:\n" ); + sb.append( " " ); + DebugUtil.dump( sb, authInfo ); + sb.append( "\n" ); + sb.append( " pubKeyAuth:\n" ); + sb.append( " " ); + DebugUtil.dump( sb, pubKeyAuth ); + return sb.toString(); + } + + + @Override + public String toString() + { + return "TsRequest(negoToken=" + Arrays.toString( negoToken ) + ", authInfo=" + + Arrays.toString( authInfo ) + ", pubKeyAuth=" + Arrays.toString( pubKeyAuth ) + ")"; + } + } + + static void getByteAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) + throws MalformedChallengeException + { + final byte bufByte = buf.get(); + if ( bufByte != expectedValue ) + { + parseError( buf, errorMessage + expectMessage( expectedValue, bufByte ) ); + } + } + + private static String expectMessage( final int expectedValue, final int realValue ) + { + return "(expected " + String.format( "%02X", expectedValue ) + ", got " + String.format( "%02X", realValue ) + + ")"; + } + + static int parseLength( final ByteBuffer buf ) + { + byte bufByte = buf.get(); + if ( bufByte == 0x80 ) + { + return -1; // infinite + } + if ( ( bufByte & 0x80 ) == 0x80 ) + { + final int size = bufByte & 0x7f; + int length = 0; + for ( int i = 0; i < size; i++ ) + { + bufByte = buf.get(); + length = ( length << 8 ) + ( bufByte & 0xff ); + } + return length; + } + else + { + return bufByte; + } + } + + static void getLengthAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) + throws MalformedChallengeException + { + final int bufLength = parseLength( buf ); + if ( expectedValue != bufLength ) + { + parseError( buf, errorMessage + expectMessage( expectedValue, bufLength ) ); + } + } + + static int getAndAssertContentSpecificTag( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException + { + final byte bufByte = buf.get(); + if ( ( bufByte & 0xe0 ) != 0xa0 ) + { + parseError( buf, errorMessage + ": wrong content-specific tag " + String.format( "%02X", bufByte ) ); + } + final int tag = bufByte & 0x1f; + return tag; + } + + static void parseError( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException + { + throw new MalformedChallengeException( + "Error parsing TsRequest (position:" + buf.position() + "): " + errorMessage ); + } + + static byte[] encodeLength( final int length ) + { + if ( length < 128 ) + { + final byte[] encoded = new byte[1]; + encoded[0] = ( byte ) length; + return encoded; + } + + int size = 1; + + int val = length; + while ( ( val >>>= 8 ) != 0 ) + { + size++; + } + + final byte[] encoded = new byte[1 + size]; + encoded[0] = ( byte ) ( size | 0x80 ); + + int shift = ( size - 1 ) * 8; + for ( int i = 0; i < size; i++ ) + { + encoded[i + 1] = ( byte ) ( length >> shift ); + shift -= 8; + } + + return encoded; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java new file mode 100644 index 0000000000..309101bde6 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java @@ -0,0 +1,44 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.auth; + + +import org.apache.http.auth.AuthScheme; +import org.apache.http.auth.AuthSchemeProvider; +import org.apache.http.protocol.HttpContext; + + +public class CredSspSchemeFactory implements AuthSchemeProvider +{ + + @Override + public AuthScheme create( final HttpContext context ) + { + return new CredSspScheme(); + } +} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java b/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java new file mode 100644 index 0000000000..862ab357ff --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java @@ -0,0 +1,96 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.auth; + + +import java.nio.ByteBuffer; + + +/** + * Simple debugging utility class for CredSSP and NTLM implementations. + */ +class DebugUtil +{ + + public static String dump( final ByteBuffer buf ) + { + final ByteBuffer dup = buf.duplicate(); + final StringBuilder sb = new StringBuilder( dup.toString() ); + sb.append( ": " ); + while ( dup.position() < dup.limit() ) + { + sb.append( String.format( "%02X ", dup.get() ) ); + } + return sb.toString(); + } + + + public static void dump( final StringBuilder sb, final byte[] bytes ) + { + if ( bytes == null ) + { + sb.append( "null" ); + return; + } + for ( byte b : bytes ) + { + sb.append( String.format( "%02X ", b ) ); + } + } + + + public static String dump( final byte[] bytes ) + { + final StringBuilder sb = new StringBuilder(); + dump( sb, bytes ); + return sb.toString(); + } + + + public static byte[] fromHex( final String hex ) + { + int i = 0; + final byte[] bytes = new byte[200000]; + int h = 0; + while ( h < hex.length() ) + { + if ( hex.charAt( h ) == ' ' ) + { + h++; + } + final String str = hex.substring( h, h + 2 ); + bytes[i] = ( byte ) Integer.parseInt( str, 16 ); + i++; + h = h + 2; + } + final byte[] outbytes = new byte[i]; + System.arraycopy( bytes, 0, outbytes, 0, i ); + return outbytes; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 1a7dc8b575..216f43f45c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -26,20 +26,21 @@ */ package org.apache.http.impl.auth; -import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; +import org.apache.http.Consts; import java.security.Key; import java.security.MessageDigest; import java.util.Arrays; import java.util.Locale; +import java.util.Random; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.Certificate; import org.apache.commons.codec.binary.Base64; -import org.apache.http.Consts; -import org.apache.http.util.CharsetUtils; -import org.apache.http.util.EncodingUtils; /** * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM @@ -50,7 +51,7 @@ final class NTLMEngineImpl implements NTLMEngine { /** Unicode encoding */ - private static final Charset UNICODE_LITTLE_UNMARKED = CharsetUtils.lookup("UnicodeLittleUnmarked"); + private static final Charset UNICODE_LITTLE_UNMARKED = Charset.forName("UnicodeLittleUnmarked"); /** Character encoding */ private static final Charset DEFAULT_CHARSET = Consts.ASCII; @@ -58,22 +59,41 @@ final class NTLMEngineImpl implements NTLMEngine { // http://davenport.sourceforge.net/ntlm.html // and // http://msdn.microsoft.com/en-us/library/cc236650%28v=prot.20%29.aspx - protected static final int FLAG_REQUEST_UNICODE_ENCODING = 0x00000001; // Unicode string encoding requested - protected static final int FLAG_REQUEST_TARGET = 0x00000004; // Requests target field - protected static final int FLAG_REQUEST_SIGN = 0x00000010; // Requests all messages have a signature attached, in NEGOTIATE message. - protected static final int FLAG_REQUEST_SEAL = 0x00000020; // Request key exchange for message confidentiality in NEGOTIATE message. MUST be used in conjunction with 56BIT. - protected static final int FLAG_REQUEST_LAN_MANAGER_KEY = 0x00000080; // Request Lan Manager key instead of user session key - protected static final int FLAG_REQUEST_NTLMv1 = 0x00000200; // Request NTLMv1 security. MUST be set in NEGOTIATE and CHALLENGE both - protected static final int FLAG_DOMAIN_PRESENT = 0x00001000; // Domain is present in message - protected static final int FLAG_WORKSTATION_PRESENT = 0x00002000; // Workstation is present in message - protected static final int FLAG_REQUEST_ALWAYS_SIGN = 0x00008000; // Requests a signature block on all messages. Overridden by REQUEST_SIGN and REQUEST_SEAL. - protected static final int FLAG_REQUEST_NTLM2_SESSION = 0x00080000; // From server in challenge, requesting NTLM2 session security - protected static final int FLAG_REQUEST_VERSION = 0x02000000; // Request protocol version - protected static final int FLAG_TARGETINFO_PRESENT = 0x00800000; // From server in challenge message, indicating targetinfo is present - protected static final int FLAG_REQUEST_128BIT_KEY_EXCH = 0x20000000; // Request explicit 128-bit key exchange - protected static final int FLAG_REQUEST_EXPLICIT_KEY_EXCH = 0x40000000; // Request explicit key exchange - protected static final int FLAG_REQUEST_56BIT_ENCRYPTION = 0x80000000; // Must be used in conjunction with SEAL - + // [MS-NLMP] section 2.2.2.5 + static final int FLAG_REQUEST_UNICODE_ENCODING = 0x00000001; // Unicode string encoding requested + static final int FLAG_REQUEST_OEM_ENCODING = 0x00000002; // OEM string encoding requested + static final int FLAG_REQUEST_TARGET = 0x00000004; // Requests target field + static final int FLAG_REQUEST_SIGN = 0x00000010; // Requests all messages have a signature attached, in NEGOTIATE message. + static final int FLAG_REQUEST_SEAL = 0x00000020; // Request key exchange for message confidentiality in NEGOTIATE message. MUST be used in conjunction with 56BIT. + static final int FLAG_REQUEST_LAN_MANAGER_KEY = 0x00000080; // Request Lan Manager key instead of user session key + static final int FLAG_REQUEST_NTLMv1 = 0x00000200; // Request NTLMv1 security. MUST be set in NEGOTIATE and CHALLENGE both + static final int FLAG_DOMAIN_PRESENT = 0x00001000; // Domain is present in message + static final int FLAG_WORKSTATION_PRESENT = 0x00002000; // Workstation is present in message + static final int FLAG_REQUEST_ALWAYS_SIGN = 0x00008000; // Requests a signature block on all messages. Overridden by REQUEST_SIGN and REQUEST_SEAL. + static final int FLAG_REQUEST_NTLM2_SESSION = 0x00080000; // From server in challenge, requesting NTLM2 session security + static final int FLAG_REQUEST_VERSION = 0x02000000; // Request protocol version + static final int FLAG_TARGETINFO_PRESENT = 0x00800000; // From server in challenge message, indicating targetinfo is present + static final int FLAG_REQUEST_128BIT_KEY_EXCH = 0x20000000; // Request explicit 128-bit key exchange + static final int FLAG_REQUEST_EXPLICIT_KEY_EXCH = 0x40000000; // Request explicit key exchange + static final int FLAG_REQUEST_56BIT_ENCRYPTION = 0x80000000; // Must be used in conjunction with SEAL + + // Attribute-value identifiers (AvId) + // according to [MS-NLMP] section 2.2.2.1 + static final int MSV_AV_EOL = 0x0000; // Indicates that this is the last AV_PAIR in the list. + static final int MSV_AV_NB_COMPUTER_NAME = 0x0001; // The server's NetBIOS computer name. + static final int MSV_AV_NB_DOMAIN_NAME = 0x0002; // The server's NetBIOS domain name. + static final int MSV_AV_DNS_COMPUTER_NAME = 0x0003; // The fully qualified domain name (FQDN) of the computer. + static final int MSV_AV_DNS_DOMAIN_NAME = 0x0004; // The FQDN of the domain. + static final int MSV_AV_DNS_TREE_NAME = 0x0005; // The FQDN of the forest. + static final int MSV_AV_FLAGS = 0x0006; // A 32-bit value indicating server or client configuration. + static final int MSV_AV_TIMESTAMP = 0x0007; // server local time + static final int MSV_AV_SINGLE_HOST = 0x0008; // A Single_Host_Data structure. + static final int MSV_AV_TARGET_NAME = 0x0009; // The SPN of the target server. + static final int MSV_AV_CHANNEL_BINDINGS = 0x000A; // A channel bindings hash. + + static final int MSV_AV_FLAGS_ACCOUNT_AUTH_CONSTAINED = 0x00000001; // Indicates to the client that the account authentication is constrained. + static final int MSV_AV_FLAGS_MIC = 0x00000002; // Indicates that the client is providing message integrity in the MIC field in the AUTHENTICATE_MESSAGE. + static final int MSV_AV_FLAGS_UNTRUSTED_TARGET_SPN = 0x00000004; // Indicates that the client is providing a target SPN generated from an untrusted source. /** Secure random generator */ private static final java.security.SecureRandom RND_GEN; @@ -87,46 +107,34 @@ final class NTLMEngineImpl implements NTLMEngine { } /** The signature string as bytes in the default encoding */ - private static final byte[] SIGNATURE; - - static { - final byte[] bytesWithoutNull = "NTLMSSP".getBytes(Consts.ASCII); - SIGNATURE = new byte[bytesWithoutNull.length + 1]; - System.arraycopy(bytesWithoutNull, 0, SIGNATURE, 0, bytesWithoutNull.length); - SIGNATURE[bytesWithoutNull.length] = (byte) 0x00; + private static final byte[] SIGNATURE = getNullTerminatedAsciiString("NTLMSSP"); + + // Key derivation magic strings for the SIGNKEY algorithm defined in + // [MS-NLMP] section 3.4.5.2 + private static final byte[] SIGN_MAGIC_SERVER = getNullTerminatedAsciiString( + "session key to server-to-client signing key magic constant"); + private static final byte[] SIGN_MAGIC_CLIENT = getNullTerminatedAsciiString( + "session key to client-to-server signing key magic constant"); + private static final byte[] SEAL_MAGIC_SERVER = getNullTerminatedAsciiString( + "session key to server-to-client sealing key magic constant"); + private static final byte[] SEAL_MAGIC_CLIENT = getNullTerminatedAsciiString( + "session key to client-to-server sealing key magic constant"); + + // prefix for GSS API channel binding + private static final byte[] MAGIC_TLS_SERVER_ENDPOINT = "tls-server-end-point:".getBytes(Consts.ASCII); + + private static byte[] getNullTerminatedAsciiString( final String source ) + { + final byte[] bytesWithoutNull = source.getBytes(Consts.ASCII); + final byte[] target = new byte[bytesWithoutNull.length + 1]; + System.arraycopy(bytesWithoutNull, 0, target, 0, bytesWithoutNull.length); + target[bytesWithoutNull.length] = (byte) 0x00; + return target; } private static final String TYPE_1_MESSAGE = new Type1Message().getResponse(); - /** - * Returns the response for the given message. - * - * @param message - * the message that was received from the server. - * @param username - * the username to authenticate with. - * @param password - * the password to authenticate with. - * @param host - * The host. - * @param domain - * the NT domain to authenticate in. - * @return The response. - * @throws org.apache.http.HttpException - * If the messages cannot be retrieved. - */ - static String getResponseFor(final String message, final String username, final String password, - final String host, final String domain) throws NTLMEngineException { - - final String response; - if (message == null || message.trim().equals("")) { - response = getType1Message(host, domain); - } else { - final Type2Message t2m = new Type2Message(message); - response = getType3Message(username, password, host, domain, t2m.getChallenge(), t2m - .getFlags(), t2m.getTarget(), t2m.getTargetInfo()); - } - return response; + NTLMEngineImpl() { } /** @@ -140,7 +148,7 @@ static String getResponseFor(final String message, final String username, final * The domain to authenticate with. * @return String the message to add to the HTTP request header. */ - static String getType1Message(final String host, final String domain) throws NTLMEngineException { + static String getType1Message(final String host, final String domain) { // For compatibility reason do not include domain and host in type 1 message //return new Type1Message(domain, host).getResponse(); return TYPE_1_MESSAGE; @@ -173,26 +181,32 @@ static String getType3Message(final String user, final String password, final St targetInformation).getResponse(); } - /** Strip dot suffix from a name */ - private static String stripDotSuffix(final String value) { - if (value == null) { - return null; - } - final int index = value.indexOf("."); - if (index != -1) { - return value.substring(0, index); - } - return value; - } - - /** Convert host to standard form */ - private static String convertHost(final String host) { - return stripDotSuffix(host); - } - - /** Convert domain to standard form */ - private static String convertDomain(final String domain) { - return stripDotSuffix(domain); + /** + * Creates the type 3 message using the given server nonce. The type 3 + * message includes all the information for authentication, host, domain, + * username and the result of encrypting the nonce sent by the server using + * the user's password as the key. + * + * @param user + * The user name. This should not include the domain name. + * @param password + * The password. + * @param host + * The host that is originating the authentication request. + * @param domain + * The domain to authenticate within. + * @param nonce + * the 8 byte array the server sent. + * @return The type 3 message. + * @throws NTLMEngineException + * If {@encrypt(byte[],byte[])} fails. + */ + static String getType3Message(final String user, final String password, final String host, final String domain, + final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation, + final Certificate peerServerCertificate, final byte[] type1Message, final byte[] type2Message) + throws NTLMEngineException { + return new Type3Message(domain, host, user, password, nonce, type2Flags, target, + targetInformation, peerServerCertificate, type1Message, type2Message).getResponse(); } private static int readULong(final byte[] src, final int index) throws NTLMEngineException { @@ -223,31 +237,28 @@ private static byte[] readSecurityBuffer(final byte[] src, final int index) thro } /** Calculate a challenge block */ - private static byte[] makeRandomChallenge() throws NTLMEngineException { - if (RND_GEN == null) { - throw new NTLMEngineException("Random generator not available"); - } + private static byte[] makeRandomChallenge(final Random random) throws NTLMEngineException { final byte[] rval = new byte[8]; - synchronized (RND_GEN) { - RND_GEN.nextBytes(rval); + synchronized (random) { + random.nextBytes(rval); } return rval; } /** Calculate a 16-byte secondary key */ - private static byte[] makeSecondaryKey() throws NTLMEngineException { - if (RND_GEN == null) { - throw new NTLMEngineException("Random generator not available"); - } + private static byte[] makeSecondaryKey(final Random random) throws NTLMEngineException { final byte[] rval = new byte[16]; - synchronized (RND_GEN) { - RND_GEN.nextBytes(rval); + synchronized (random) { + random.nextBytes(rval); } return rval; } protected static class CipherGen { + protected final Random random; + protected final long currentTime; + protected final String domain; protected final String user; protected final String password; @@ -279,10 +290,25 @@ protected static class CipherGen { protected byte[] ntlm2SessionResponseUserSessionKey = null; protected byte[] lanManagerSessionKey = null; + @Deprecated public CipherGen(final String domain, final String user, final String password, final byte[] challenge, final String target, final byte[] targetInformation, final byte[] clientChallenge, final byte[] clientChallenge2, final byte[] secondaryKey, final byte[] timestamp) { + this(RND_GEN, System.currentTimeMillis(), + domain, user, password, challenge, target, targetInformation, + clientChallenge, clientChallenge2, + secondaryKey, timestamp); + } + + public CipherGen(final Random random, final long currentTime, + final String domain, final String user, final String password, + final byte[] challenge, final String target, final byte[] targetInformation, + final byte[] clientChallenge, final byte[] clientChallenge2, + final byte[] secondaryKey, final byte[] timestamp) { + this.random = random; + this.currentTime = currentTime; + this.domain = domain; this.target = target; this.user = user; @@ -295,16 +321,31 @@ public CipherGen(final String domain, final String user, final String password, this.timestamp = timestamp; } - public CipherGen(final String domain, final String user, final String password, - final byte[] challenge, final String target, final byte[] targetInformation) { - this(domain, user, password, challenge, target, targetInformation, null, null, null, null); + @Deprecated + public CipherGen(final String domain, + final String user, + final String password, + final byte[] challenge, + final String target, + final byte[] targetInformation) { + this(RND_GEN, System.currentTimeMillis(), domain, user, password, challenge, target, targetInformation); + } + + public CipherGen(final Random random, final long currentTime, + final String domain, + final String user, + final String password, + final byte[] challenge, + final String target, + final byte[] targetInformation) { + this(random, currentTime, domain, user, password, challenge, target, targetInformation, null, null, null, null); } /** Calculate and return client challenge */ public byte[] getClientChallenge() throws NTLMEngineException { if (clientChallenge == null) { - clientChallenge = makeRandomChallenge(); + clientChallenge = makeRandomChallenge(random); } return clientChallenge; } @@ -313,7 +354,7 @@ public byte[] getClientChallenge() public byte[] getClientChallenge2() throws NTLMEngineException { if (clientChallenge2 == null) { - clientChallenge2 = makeRandomChallenge(); + clientChallenge2 = makeRandomChallenge(random); } return clientChallenge2; } @@ -322,7 +363,7 @@ public byte[] getClientChallenge2() public byte[] getSecondaryKey() throws NTLMEngineException { if (secondaryKey == null) { - secondaryKey = makeSecondaryKey(); + secondaryKey = makeSecondaryKey(random); } return secondaryKey; } @@ -384,7 +425,7 @@ public byte[] getNTLMv2Hash() /** Calculate a timestamp */ public byte[] getTimestamp() { if (timestamp == null) { - long time = System.currentTimeMillis(); + long time = this.currentTime; time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch. time *= 10000; // tenths of a microsecond. // convert to little-endian byte array. @@ -552,7 +593,7 @@ static byte[] RC4(final byte[] value, final byte[] key) static byte[] ntlm2SessionResponse(final byte[] ntlmHash, final byte[] challenge, final byte[] clientChallenge) throws NTLMEngineException { try { - final MessageDigest md5 = MessageDigest.getInstance("MD5"); + final MessageDigest md5 = getMD5(); md5.update(challenge); md5.update(clientChallenge); final byte[] digest = md5.digest(); @@ -719,6 +760,191 @@ private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, fi return lmv2Response; } + static enum Mode + { + CLIENT, SERVER; + } + + static class Handle + { + final private byte[] exportedSessionKey; + private byte[] signingKey; + private byte[] sealingKey; + private Cipher rc4; + final Mode mode; + final private boolean isConnection; + int sequenceNumber = 0; + + + Handle( final byte[] exportedSessionKey, final Mode mode, final boolean isConnection ) + throws NTLMEngineException + { + this.exportedSessionKey = exportedSessionKey; + this.isConnection = isConnection; + this.mode = mode; + try + { + final MessageDigest signMd5 = getMD5(); + final MessageDigest sealMd5 = getMD5(); + signMd5.update( exportedSessionKey ); + sealMd5.update( exportedSessionKey ); + if ( mode == Mode.CLIENT ) + { + signMd5.update( SIGN_MAGIC_CLIENT ); + sealMd5.update( SEAL_MAGIC_CLIENT ); + } + else + { + signMd5.update( SIGN_MAGIC_SERVER ); + sealMd5.update( SEAL_MAGIC_SERVER ); + } + signingKey = signMd5.digest(); + sealingKey = sealMd5.digest(); + } + catch ( final Exception e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + rc4 = initCipher(); + } + + public byte[] getSigningKey() + { + return signingKey; + } + + + public byte[] getSealingKey() + { + return sealingKey; + } + + private Cipher initCipher() throws NTLMEngineException + { + Cipher cipher; + try + { + cipher = Cipher.getInstance( "RC4" ); + if ( mode == Mode.CLIENT ) + { + cipher.init( Cipher.ENCRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); + } + else + { + cipher.init( Cipher.DECRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); + } + } + catch ( Exception e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + return cipher; + } + + + private void advanceMessageSequence() throws NTLMEngineException + { + if ( !isConnection ) + { + final MessageDigest sealMd5 = getMD5(); + sealMd5.update( sealingKey ); + final byte[] seqNumBytes = new byte[4]; + writeULong( seqNumBytes, sequenceNumber, 0 ); + sealMd5.update( seqNumBytes ); + sealingKey = sealMd5.digest(); + initCipher(); + } + sequenceNumber++; + } + + private byte[] encrypt( final byte[] data ) throws NTLMEngineException + { + return rc4.update( data ); + } + + private byte[] decrypt( final byte[] data ) throws NTLMEngineException + { + return rc4.update( data ); + } + + private byte[] computeSignature( final byte[] message ) throws NTLMEngineException + { + final byte[] sig = new byte[16]; + + // version + sig[0] = 0x01; + sig[1] = 0x00; + sig[2] = 0x00; + sig[3] = 0x00; + + // HMAC (first 8 bytes) + final HMACMD5 hmacMD5 = new HMACMD5( signingKey ); + hmacMD5.update( encodeLong( sequenceNumber ) ); + hmacMD5.update( message ); + final byte[] hmac = hmacMD5.getOutput(); + final byte[] trimmedHmac = new byte[8]; + System.arraycopy( hmac, 0, trimmedHmac, 0, 8 ); + final byte[] encryptedHmac = encrypt( trimmedHmac ); + System.arraycopy( encryptedHmac, 0, sig, 4, 8 ); + + // sequence number + encodeLong( sig, 12, sequenceNumber ); + + return sig; + } + + private boolean validateSignature( final byte[] signature, final byte message[] ) throws NTLMEngineException + { + final byte[] computedSignature = computeSignature( message ); + // log.info( "SSSSS validateSignature("+seqNumber+")\n" + // + " received: " + DebugUtil.dump( signature ) + "\n" + // + " computed: " + DebugUtil.dump( computedSignature ) ); + return Arrays.equals( signature, computedSignature ); + } + + public byte[] signAndEncryptMessage( final byte[] cleartextMessage ) throws NTLMEngineException + { + final byte[] encryptedMessage = encrypt( cleartextMessage ); + final byte[] signature = computeSignature( cleartextMessage ); + final byte[] outMessage = new byte[signature.length + encryptedMessage.length]; + System.arraycopy( signature, 0, outMessage, 0, signature.length ); + System.arraycopy( encryptedMessage, 0, outMessage, signature.length, encryptedMessage.length ); + advanceMessageSequence(); + return outMessage; + } + + public byte[] decryptAndVerifySignedMessage( final byte[] inMessage ) throws NTLMEngineException + { + final byte[] signature = new byte[16]; + System.arraycopy( inMessage, 0, signature, 0, signature.length ); + final byte[] encryptedMessage = new byte[inMessage.length - 16]; + System.arraycopy( inMessage, 16, encryptedMessage, 0, encryptedMessage.length ); + final byte[] cleartextMessage = decrypt( encryptedMessage ); + if ( !validateSignature( signature, cleartextMessage ) ) + { + throw new NTLMEngineException( "Wrong signature" ); + } + advanceMessageSequence(); + return cleartextMessage; + } + + } + + private static byte[] encodeLong( final int value ) + { + final byte[] enc = new byte[4]; + encodeLong( enc, 0, value ); + return enc; + } + + private static void encodeLong( final byte[] buf, final int offset, final int value ) + { + buf[offset + 0] = ( byte ) ( value & 0xff ); + buf[offset + 1] = ( byte ) ( value >> 8 & 0xff ); + buf[offset + 2] = ( byte ) ( value >> 16 & 0xff ); + buf[offset + 3] = ( byte ) ( value >> 24 & 0xff ); + } + /** * Creates the NTLMv2 blob from the given target information block and * client challenge. @@ -802,21 +1028,65 @@ private static void oddParity(final byte[] bytes) { } } + /** + * Find the character set based on the flags. + * @param flags is the flags. + * @return the character set. + */ + private static Charset getCharset(final int flags) throws NTLMEngineException + { + if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { + return DEFAULT_CHARSET; + } else { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException( "Unicode not supported" ); + } + return UNICODE_LITTLE_UNMARKED; + } + } + + /** Strip dot suffix from a name */ + private static String stripDotSuffix(final String value) { + if (value == null) { + return null; + } + final int index = value.indexOf("."); + if (index != -1) { + return value.substring(0, index); + } + return value; + } + + /** Convert host to standard form */ + private static String convertHost(final String host) { + return stripDotSuffix(host); + } + + /** Convert domain to standard form */ + private static String convertDomain(final String domain) { + return stripDotSuffix(domain); + } + /** NTLM message generation, base class */ static class NTLMMessage { /** The current response */ - private byte[] messageContents = null; + protected byte[] messageContents = null; /** The current output position */ - private int currentOutputPosition = 0; + protected int currentOutputPosition = 0; /** Constructor to use when message contents are not yet known */ NTLMMessage() { } - /** Constructor to use when message contents are known */ + /** Constructor taking a string */ NTLMMessage(final String messageBody, final int expectedType) throws NTLMEngineException { - messageContents = Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET)); + this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET)), expectedType); + } + + /** Constructor to use when message bytes are known */ + NTLMMessage(final byte[] message, final int expectedType) throws NTLMEngineException { + messageContents = message; // Look for NTLM message if (messageContents.length < SIGNATURE.length) { throw new NTLMEngineException("NTLM message decoding error - packet too short"); @@ -888,7 +1158,7 @@ protected byte[] readSecurityBuffer(final int position) throws NTLMEngineExcepti * Prepares the object to create a response of the given length. * * @param maxlength - * the maximum length of the response to prepare, not + * the maximum length of the response to prepare, * including the type and the signature (which this method * adds). */ @@ -946,18 +1216,26 @@ protected void addULong(final int value) { * * @return The response as above. */ - String getResponse() { + public String getResponse() { + return new String(Base64.encodeBase64(getBytes()), Consts.ASCII); + } + + public byte[] getBytes() { + if (messageContents == null) { + buildMessage(); + } final byte[] resp; - if (messageContents.length > currentOutputPosition) { + if ( messageContents.length > currentOutputPosition ) { final byte[] tmp = new byte[currentOutputPosition]; - System.arraycopy(messageContents, 0, tmp, 0, currentOutputPosition); - resp = tmp; - } else { - resp = messageContents; + System.arraycopy( messageContents, 0, tmp, 0, currentOutputPosition ); + messageContents = tmp; } - return EncodingUtils.getAsciiString(Base64.encodeBase64(resp)); + return messageContents; } + protected void buildMessage() { + throw new RuntimeException("Message builder not implemented for "+getClass().getName()); + } } /** Type 1 message assembly class */ @@ -965,12 +1243,16 @@ static class Type1Message extends NTLMMessage { private final byte[] hostBytes; private final byte[] domainBytes; + private final int flags; Type1Message(final String domain, final String host) throws NTLMEngineException { + this(domain, host, null); + } + + Type1Message(final String domain, final String host, final Integer flags) throws NTLMEngineException { super(); - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } + this.flags = ((flags == null)?getDefaultFlags():flags); + // Strip off domain name from the host! final String unqualifiedHost = convertHost(host); // Use only the base domain name! @@ -986,56 +1268,72 @@ static class Type1Message extends NTLMMessage { super(); hostBytes = null; domainBytes = null; + flags = getDefaultFlags(); + } + + private int getDefaultFlags() { + return + //FLAG_WORKSTATION_PRESENT | + //FLAG_DOMAIN_PRESENT | + + // Required flags + //FLAG_REQUEST_LAN_MANAGER_KEY | + FLAG_REQUEST_NTLMv1 | + FLAG_REQUEST_NTLM2_SESSION | + + // Protocol version request + FLAG_REQUEST_VERSION | + + // Recommended privacy settings + FLAG_REQUEST_ALWAYS_SIGN | + //FLAG_REQUEST_SEAL | + //FLAG_REQUEST_SIGN | + + // These must be set according to documentation, based on use of SEAL above + FLAG_REQUEST_128BIT_KEY_EXCH | + FLAG_REQUEST_56BIT_ENCRYPTION | + //FLAG_REQUEST_EXPLICIT_KEY_EXCH | + + FLAG_REQUEST_UNICODE_ENCODING; + } + /** * Getting the response involves building the message before returning * it */ @Override - String getResponse() { + protected void buildMessage() { + int domainBytesLength = 0; + if ( domainBytes != null ) { + domainBytesLength = domainBytes.length; + } + int hostBytesLength = 0; + if ( hostBytes != null ) { + hostBytesLength = hostBytes.length; + } + // Now, build the message. Calculate its length first, including // signature or type. - final int finalLength = 32 + 8 /*+ hostBytes.length + domainBytes.length */; + final int finalLength = 32 + 8 + hostBytesLength + domainBytesLength; // Set up the response. This will initialize the signature, message // type, and flags. prepareResponse(finalLength, 1); // Flags. These are the complete set of flags we support. - addULong( - //FLAG_WORKSTATION_PRESENT | - //FLAG_DOMAIN_PRESENT | - - // Required flags - //FLAG_REQUEST_LAN_MANAGER_KEY | - FLAG_REQUEST_NTLMv1 | - FLAG_REQUEST_NTLM2_SESSION | - - // Protocol version request - FLAG_REQUEST_VERSION | - - // Recommended privacy settings - FLAG_REQUEST_ALWAYS_SIGN | - //FLAG_REQUEST_SEAL | - //FLAG_REQUEST_SIGN | - - // These must be set according to documentation, based on use of SEAL above - FLAG_REQUEST_128BIT_KEY_EXCH | - FLAG_REQUEST_56BIT_ENCRYPTION | - //FLAG_REQUEST_EXPLICIT_KEY_EXCH | - - FLAG_REQUEST_UNICODE_ENCODING); + addULong(flags); // Domain length (two times). - addUShort(/*domainBytes.length*/0); - addUShort(/*domainBytes.length*/0); + addUShort(domainBytesLength); + addUShort(domainBytesLength); // Domain offset. - addULong(/*hostBytes.length +*/ 32 + 8); + addULong(hostBytesLength + 32 + 8); // Host length (two times). - addUShort(/*hostBytes.length*/0); - addUShort(/*hostBytes.length*/0); + addUShort(hostBytesLength); + addUShort(hostBytesLength); // Host offset (always 32 + 8). addULong(32 + 8); @@ -1055,20 +1353,22 @@ String getResponse() { if (domainBytes != null) { addBytes(domainBytes); } - - return super.getResponse(); } } /** Type 2 message class */ static class Type2Message extends NTLMMessage { - protected byte[] challenge; + protected final byte[] challenge; protected String target; protected byte[] targetInfo; - protected int flags; + protected final int flags; - Type2Message(final String message) throws NTLMEngineException { + Type2Message(final String messageBody) throws NTLMEngineException { + this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET))); + } + + Type2Message(final byte[] message) throws NTLMEngineException { super(message, 2); // Type 2 message is laid out as follows: @@ -1091,12 +1391,6 @@ static class Type2Message extends NTLMMessage { flags = readULong(20); - if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { - throw new NTLMEngineException( - "NTLM type 2 message indicates no support for Unicode. Flags are: " - + Integer.toString(flags)); - } - // Do the target! target = null; // The TARGET_DESIRED flag is said to not have understood semantics @@ -1105,11 +1399,7 @@ static class Type2Message extends NTLMMessage { if (getMessageLength() >= 12 + 8) { final byte[] bytes = readSecurityBuffer(12); if (bytes.length != 0) { - try { - target = new String(bytes, "UnicodeLittleUnmarked"); - } catch (final UnsupportedEncodingException e) { - throw new NTLMEngineException(e.getMessage(), e); - } + target = new String(bytes, getCharset(flags)); } } @@ -1148,32 +1438,113 @@ int getFlags() { /** Type 3 message assembly class */ static class Type3Message extends NTLMMessage { + // For mic computation + protected final byte[] type1Message; + protected final byte[] type2Message; // Response flags from the type2 message - protected int type2Flags; + protected final int type2Flags; - protected byte[] domainBytes; - protected byte[] hostBytes; - protected byte[] userBytes; + protected final byte[] domainBytes; + protected final byte[] hostBytes; + protected final byte[] userBytes; protected byte[] lmResp; protected byte[] ntResp; - protected byte[] sessionKey; + protected final byte[] sessionKey; + protected final byte[] exportedSessionKey; + + protected final boolean computeMic; + + /** More primitive constructor: don't include cert or previous messages. + */ + Type3Message(final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation) + throws NTLMEngineException { + this(domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); + } + + /** More primitive constructor: don't include cert or previous messages. + */ + Type3Message(final Random random, final long currentTime, + final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation) + throws NTLMEngineException { + this(random, currentTime, domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); + } + /** Constructor. Pass the arguments we will need */ + Type3Message(final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation, + final Certificate peerServerCertificate, + final byte[] type1Message, + final byte[] type2Message) + throws NTLMEngineException { + this(RND_GEN, System.currentTimeMillis(), domain, host, user, password, nonce, type2Flags, target, targetInformation, peerServerCertificate, type1Message, type2Message); + } /** Constructor. Pass the arguments we will need */ - Type3Message(final String domain, final String host, final String user, final String password, final byte[] nonce, - final int type2Flags, final String target, final byte[] targetInformation) - throws NTLMEngineException { + Type3Message(final Random random, final long currentTime, + final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation, + final Certificate peerServerCertificate, + final byte[] type1Message, + final byte[] type2Message) + throws NTLMEngineException { + + if (random == null) { + throw new NTLMEngineException("Random generator not available"); + } + // Save the flags this.type2Flags = type2Flags; + this.type1Message = type1Message; + this.type2Message = type2Message; // Strip off domain name from the host! final String unqualifiedHost = convertHost(host); // Use only the base domain name! final String unqualifiedDomain = convertDomain(domain); - // Create a cipher generator class. Use domain BEFORE it gets modified! - final CipherGen gen = new CipherGen(unqualifiedDomain, user, password, nonce, target, targetInformation); + byte[] responseTargetInformation = targetInformation; + if (peerServerCertificate != null) { + responseTargetInformation = addGssMicAvsToTargetInfo(targetInformation, peerServerCertificate); + computeMic = true; + } else { + computeMic = false; + } + + // Create a cipher generator class. Use domain BEFORE it gets modified! + final CipherGen gen = new CipherGen(random, currentTime, + unqualifiedDomain, + user, + password, + nonce, + target, + responseTargetInformation); // Use the new code to calculate the responses, including v2 if that // seems warranted. @@ -1226,25 +1597,37 @@ static class Type3Message extends NTLMMessage { if ((type2Flags & FLAG_REQUEST_SIGN) != 0) { if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) { - sessionKey = RC4(gen.getSecondaryKey(), userSessionKey); + exportedSessionKey = gen.getSecondaryKey(); + sessionKey = RC4(exportedSessionKey, userSessionKey); } else { sessionKey = userSessionKey; + exportedSessionKey = sessionKey; } } else { + if (computeMic) { + throw new NTLMEngineException("Cannot sign/seal: no exported session key"); + } sessionKey = null; + exportedSessionKey = null; } - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } - hostBytes = unqualifiedHost != null ? unqualifiedHost.getBytes(UNICODE_LITTLE_UNMARKED) : null; - domainBytes = unqualifiedDomain != null ? unqualifiedDomain - .toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED) : null; - userBytes = user.getBytes(UNICODE_LITTLE_UNMARKED); + final Charset charset = getCharset(type2Flags); + hostBytes = unqualifiedHost != null ? unqualifiedHost.getBytes(charset) : null; + domainBytes = unqualifiedDomain != null ? unqualifiedDomain + .toUpperCase(Locale.ROOT).getBytes(charset) : null; + userBytes = user.getBytes(charset); + } + + public byte[] getEncryptedRandomSessionKey() { + return sessionKey; + } + + public byte[] getExportedSessionKey() { + return exportedSessionKey; } /** Assemble the response */ @Override - String getResponse() { + protected void buildMessage() { final int ntRespLen = ntResp.length; final int lmRespLen = lmResp.length; @@ -1259,7 +1642,8 @@ String getResponse() { } // Calculate the layout within the packet - final int lmRespOffset = 72; // allocate space for the version + final int lmRespOffset = 72 + // allocate space for the version + ( computeMic ? 16 : 0 ); // and MIC final int ntRespOffset = lmRespOffset + lmRespLen; final int domainOffset = ntRespOffset + ntRespLen; final int userOffset = domainOffset + domainLen; @@ -1314,6 +1698,7 @@ String getResponse() { // Flags. addULong( + /* //FLAG_WORKSTATION_PRESENT | //FLAG_DOMAIN_PRESENT | @@ -1338,6 +1723,8 @@ String getResponse() { (type2Flags & FLAG_TARGETINFO_PRESENT) | (type2Flags & FLAG_REQUEST_UNICODE_ENCODING) | (type2Flags & FLAG_REQUEST_TARGET) + */ + type2Flags ); // Version @@ -1347,6 +1734,12 @@ String getResponse() { // NTLM revision addUShort(0x0f00); + int micPosition = -1; + if ( computeMic ) { + micPosition = currentOutputPosition; + currentOutputPosition += 16; + } + // Add the actual data addBytes(lmResp); addBytes(ntResp); @@ -1357,8 +1750,69 @@ String getResponse() { addBytes(sessionKey); } - return super.getResponse(); + // Write the mic back into its slot in the message + + if (computeMic) { + // Computation of message integrity code (MIC) as specified in [MS-NLMP] section 3.2.5.1.2. + final HMACMD5 hmacMD5 = new HMACMD5( exportedSessionKey ); + hmacMD5.update( type1Message ); + hmacMD5.update( type2Message ); + hmacMD5.update( messageContents ); + final byte[] mic = hmacMD5.getOutput(); + System.arraycopy( mic, 0, messageContents, micPosition, mic.length ); + } } + + /** + * Add GSS channel binding hash and MIC flag to the targetInfo. + * Looks like this is needed if we want to use exported session key for GSS wrapping. + */ + private byte[] addGssMicAvsToTargetInfo( final byte[] originalTargetInfo, + final Certificate peerServerCertificate ) throws NTLMEngineException + { + final byte[] newTargetInfo = new byte[originalTargetInfo.length + 8 + 20]; + final int appendLength = originalTargetInfo.length - 4; // last tag is MSV_AV_EOL, do not copy that + System.arraycopy( originalTargetInfo, 0, newTargetInfo, 0, appendLength ); + writeUShort( newTargetInfo, MSV_AV_FLAGS, appendLength ); + writeUShort( newTargetInfo, 4, appendLength + 2 ); + writeULong( newTargetInfo, MSV_AV_FLAGS_MIC, appendLength + 4 ); + writeUShort( newTargetInfo, MSV_AV_CHANNEL_BINDINGS, appendLength + 8 ); + writeUShort( newTargetInfo, 16, appendLength + 10 ); + + byte[] channelBindingsHash; + try + { + final byte[] certBytes = peerServerCertificate.getEncoded(); + final MessageDigest sha256 = MessageDigest.getInstance( "SHA-256" ); + final byte[] certHashBytes = sha256.digest( certBytes ); + final byte[] channelBindingStruct = new byte[16 + 4 + MAGIC_TLS_SERVER_ENDPOINT.length + + certHashBytes.length]; + writeULong( channelBindingStruct, 0x00000035, 16 ); + System.arraycopy( MAGIC_TLS_SERVER_ENDPOINT, 0, channelBindingStruct, 20, + MAGIC_TLS_SERVER_ENDPOINT.length ); + System.arraycopy( certHashBytes, 0, channelBindingStruct, 20 + MAGIC_TLS_SERVER_ENDPOINT.length, + certHashBytes.length ); + final MessageDigest md5 = getMD5(); + channelBindingsHash = md5.digest( channelBindingStruct ); + } + catch ( CertificateEncodingException e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + catch ( NoSuchAlgorithmException e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + + System.arraycopy( channelBindingsHash, 0, newTargetInfo, appendLength + 12, 16 ); + return newTargetInfo; + } + + } + + static void writeUShort(final byte[] buffer, final int value, final int offset) { + buffer[offset] = ( byte ) ( value & 0xff ); + buffer[offset + 1] = ( byte ) ( value >> 8 & 0xff ); } static void writeULong(final byte[] buffer, final int value, final int offset) { @@ -1384,6 +1838,14 @@ static int rotintlft(final int val, final int numbits) { return ((val << numbits) | (val >>> (32 - numbits))); } + static MessageDigest getMD5() { + try { + return MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException("MD5 message digest doesn't seem to exist - fatal error: "+ex.getMessage(), ex); + } + } + /** * Cryptography support - MD4. The following class was based loosely on the * RFC and on code found at http://www.cs.umd.edu/~harry/jotp/src/md.java. @@ -1397,7 +1859,7 @@ static class MD4 { protected int C = 0x98badcfe; protected int D = 0x10325476; protected long count = 0L; - protected byte[] dataBuffer = new byte[64]; + protected final byte[] dataBuffer = new byte[64]; MD4() { } @@ -1556,20 +2018,13 @@ protected void round3(final int[] d) { * resources by Karl Wright */ static class HMACMD5 { - protected byte[] ipad; - protected byte[] opad; - protected MessageDigest md5; + protected final byte[] ipad; + protected final byte[] opad; + protected final MessageDigest md5; - HMACMD5(final byte[] input) throws NTLMEngineException { + HMACMD5(final byte[] input) { byte[] key = input; - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (final Exception ex) { - // Umm, the algorithm doesn't exist - throw an - // NTLMEngineException! - throw new NTLMEngineException( - "Error getting md5 message digest implementation: " + ex.getMessage(), ex); - } + md5 = getMD5(); // Initialize the pad buffers with the key ipad = new byte[64]; @@ -1594,7 +2049,7 @@ static class HMACMD5 { i++; } - // Very important: update the digest with the ipad buffer + // Very important: processChallenge the digest with the ipad buffer md5.reset(); md5.update(ipad); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java index 57df6141f2..1f35e61c56 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java @@ -73,9 +73,9 @@ abstract class AuthenticationStrategyImpl implements AuthenticationStrategy { AuthSchemes.SPNEGO, AuthSchemes.KERBEROS, AuthSchemes.NTLM, + AuthSchemes.CREDSSP, AuthSchemes.DIGEST, AuthSchemes.BASIC)); - private final int challengeCode; private final String headerName; diff --git a/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java b/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java index 03900e24f0..8af33b6225 100644 --- a/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java +++ b/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java @@ -29,6 +29,11 @@ import org.apache.http.Consts; import org.junit.Assert; import org.junit.Test; +import java.util.Random; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertificateFactory; +import java.security.cert.Certificate; public class TestNTLMEngineImpl { @@ -51,6 +56,9 @@ static byte toNibble(final char c) { if (c >= 'a' && c <= 'f') { return (byte) (c - 'a' + 0x0a); } + if (c >= 'A' && c <= 'F') { + return (byte) (c - 'A' + 0x0a); + } return (byte) (c - '0'); } @@ -89,6 +97,8 @@ static void checkMD4(final String input, final String hexOutput) throws Exceptio @Test public void testLMResponse() throws Exception { final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen( + new Random(1234), + 1234L, null, null, "SecREt01", @@ -107,6 +117,8 @@ public void testLMResponse() throws Exception { @Test public void testNTLMResponse() throws Exception { final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen( + new Random(1234), + 1234L, null, null, "SecREt01", @@ -125,6 +137,8 @@ public void testNTLMResponse() throws Exception { @Test public void testLMv2Response() throws Exception { final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen( + new Random(1234), + 1234L, "DOMAIN", "user", "SecREt01", @@ -143,6 +157,8 @@ public void testLMv2Response() throws Exception { @Test public void testNTLMv2Response() throws Exception { final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen( + new Random(1234), + 1234L, "DOMAIN", "user", "SecREt01", @@ -163,6 +179,8 @@ public void testNTLMv2Response() throws Exception { @Test public void testLM2SessionResponse() throws Exception { final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen( + new Random(1234), + 1234L, "DOMAIN", "user", "SecREt01", @@ -181,6 +199,8 @@ public void testLM2SessionResponse() throws Exception { @Test public void testNTLM2SessionResponse() throws Exception { final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen( + new Random(1234), + 1234L, "DOMAIN", "user", "SecREt01", @@ -199,6 +219,8 @@ public void testNTLM2SessionResponse() throws Exception { @Test public void testNTLMUserSessionKey() throws Exception { final NTLMEngineImpl.CipherGen gen = new NTLMEngineImpl.CipherGen( + new Random(1234), + 1234L, "DOMAIN", "user", "SecREt01", @@ -216,20 +238,74 @@ public void testNTLMUserSessionKey() throws Exception { @Test public void testType1Message() throws Exception { - new NTLMEngineImpl().getType1Message("myhost", "mydomain"); + final byte[] bytes = new NTLMEngineImpl.Type1Message("myhost", "mydomain").getBytes(); + final byte[] bytes2 = toBytes("4E544C4D5353500001000000018208A20C000C003800000010001000280000000501280A0000000F6D00790064006F006D00610069006E004D00590048004F0053005400"); + checkArraysMatch(bytes2, bytes); } @Test public void testType3Message() throws Exception { - new NTLMEngineImpl().getType3Message("me", "mypassword", "myhost", "mydomain", + final byte[] bytes = new NTLMEngineImpl.Type3Message( + new Random(1234), + 1234L, + "me", "mypassword", "myhost", "mydomain", toBytes("0001020304050607"), 0xffffffff, - null,null); - new NTLMEngineImpl().getType3Message("me", "mypassword", "myhost", "mydomain", + null,null).getBytes(); + checkArraysMatch(toBytes("4E544C4D53535000030000001800180048000000180018006000000004000400780000000C000C007C0000001400140088000000100010009C000000FFFFFFFF0501280A0000000FA86886A5D297814200000000000000000000000000000000EEC7568E00798491244959B9C942F4F367C5CBABEEF546F74D0045006D00790068006F00730074006D007900700061007300730077006F007200640094DDAB1EBB82C9A1AB914CAE6F199644"), + bytes); + final byte[] bytes2 = new NTLMEngineImpl.Type3Message( + new Random(1234), + 1234L, + "me", "mypassword", "myhost", "mydomain", toBytes("0001020304050607"), 0xffffffff, "mytarget", - toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000")); + toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000")).getBytes(); + checkArraysMatch(toBytes("4E544C4D53535000030000001800180048000000920092006000000004000400F20000000C000C00F600000014001400020100001000100016010000FFFFFFFF0501280A0000000F3695F1EA7B164788A437892FA7504320DA2D8CF378EBC83CE856A8FB985BF7783545828A91A13AE8010100000000000020CBFAD5DEB19D01A86886A5D29781420000000002000C0044004F004D00410049004E0001000C005300450052005600450052000400140064006F006D00610069006E002E0063006F006D00030022007300650072007600650072002E0064006F006D00610069006E002E0063006F006D0000000000000000004D0045006D00790068006F00730074006D007900700061007300730077006F0072006400BB1AAD36F11631CC7CBC8800CEEE1C99"), + bytes2); + } + + private static String cannedCert = + "-----BEGIN CERTIFICATE-----\n"+ + "MIIDIDCCAgigAwIBAgIEOqKaWTANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEQMA4GA1UEBxMH\n"+ + "TXkgQ2l0eTEYMBYGA1UEChMPTXkgT3JnYW5pemF0aW9uMRcwFQYDVQQDEw5NeSBBcHBsaWNhdGlvbjAe\n"+ + "Fw0xNzAzMTcxNDAyMzRaFw0yNzAzMTUxNDAyMzRaMFIxCzAJBgNVBAYTAlVTMRAwDgYDVQQHEwdNeSBD\n"+ + "aXR5MRgwFgYDVQQKEw9NeSBPcmdhbml6YXRpb24xFzAVBgNVBAMTDk15IEFwcGxpY2F0aW9uMIIBIjAN\n"+ + "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArc+mbViBaHeRSt82KrJ5IF+62b/Qob95Lca4DJIislTY\n"+ + "vLPIo0R1faBV8BkEeUQwo01srkf3RaGLCHNZnFal4KEzbtiUy6W+n08G5E9w9YG+WSwW2dmjvEI7k2a2\n"+ + "xqlaM4NdMKL4ONPXcxfZsMDqxDgpdkaNPKpZ10NDq6rmBTkQw/OSG0z1KLtwLkF1ZQ/3mXdjVzvP83V2\n"+ + "g17AqBazb0Z1YHsVKmkGjPqnq3niJH/6Oke4N+5k/1cE5lSJcQNGP0nqeGdJfvqQZ+gk6gH/sOngZL9X\n"+ + "hPVkpseAwHa+xuPneDSjibLgLmMt3XGDK6jGfjdp5FWqFvAD5E3LHbW9gwIDAQABMA0GCSqGSIb3DQEB\n"+ + "CwUAA4IBAQCpUXUHhl5LyMSO5Q0OktEc9AaFjZtVfknpPde6Zeh35Pqd2354ErvJSBWgzFAphda0oh2s\n"+ + "OIAFkM6LJQEnVDTbXDXN+YY8e3gb9ryfh85hkhC0XI9qp17WPSkmw8XgDfvRd6YQgKm1AnLxjOCwG2jg\n"+ + "i09iZBIWkW3ZeRAMvWPHHjvq44iZB5ZrEl0apgumS6MxpUzKOr5Pcq0jxJDw2UCj5YloFMNl+UINv2vV\n"+ + "aL/DR6ivc61dOfN1E/VNBGkkCk/AogNyucGiFMCq9hd25Y9EbkBBqObYTH1XMX+ufsJh+6hG7KDQ1e/F\n"+ + "nRrlhKwM2uRe+aSH0D6/erjDBT7tXvwn\n"+ + "-----END CERTIFICATE-----"; + + @Test + public void testType3MessageWithCert() throws Exception { + final ByteArrayInputStream fis = new ByteArrayInputStream(cannedCert.getBytes(Consts.ASCII)); + + final CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + final Certificate cert = cf.generateCertificate(fis); + + final byte[] bytes = new NTLMEngineImpl.Type3Message( + new Random(1234), + 1234L, + "me", "mypassword", "myhost", "mydomain", + toBytes("0001020304050607"), + 0xffffffff, + "mytarget", + toBytes("02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000"), + cert, + toBytes("4E544C4D5353500001000000018208A20C000C003800000010001000280000000501280A0000000F6D00790064006F006D00610069006E004D00590048004F0053005400"), + toBytes("4E544C4D5353500001000000018208A20C000C003800000010001000280000000501280A0000000F6D00790064006F006D00610069006E004D00590048004F0053005400FFFEFDFCFBFA")).getBytes(); + + checkArraysMatch(toBytes("4E544C4D53535000030000001800180058000000AE00AE0070000000040004001E0100000C000C0022010000140014002E0100001000100042010000FFFFFFFF0501280A0000000FEEFCCE4187D6CDF1F91C686C4E571D943695F1EA7B164788A437892FA7504320DA2D8CF378EBC83C59D7A3B2951929079B66621D7CF4326B010100000000000020CBFAD5DEB19D01A86886A5D29781420000000002000C0044004F004D00410049004E0001000C005300450052005600450052000400140064006F006D00610069006E002E0063006F006D00030022007300650072007600650072002E0064006F006D00610069006E002E0063006F006D0006000400020000000A00100038EDC0B7EF8D8FE9E1E6A83F6DFEB8FF00000000000000004D0045006D00790068006F00730074006D007900700061007300730077006F0072006400BB1AAD36F11631CC7CBC8800CEEE1C99"), + bytes); } @Test @@ -247,4 +323,5 @@ static void checkArraysMatch(final byte[] a1, final byte[] a2) Assert.assertEquals(a1[i],a2[i]); } } + } From fe3a913e6b02c8c5c8c73bec2f7bd66d491d3682 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 20 Mar 2017 12:26:39 +0000 Subject: [PATCH 109/204] HTTPCLIENT-1831: URIBuilder should not prepend a leading slash to relative URIs git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1787739 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/client/utils/URIBuilder.java | 44 +++++++++---------- .../http/client/utils/TestURIBuilder.java | 12 +++++ 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java index 974d34e5cb..91f198c3e2 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java @@ -146,9 +146,9 @@ private String buildString() { } } if (this.encodedPath != null) { - sb.append(normalizePath(this.encodedPath)); + sb.append(normalizePath(this.encodedPath, sb.length() == 0)); } else if (this.path != null) { - sb.append(encodePath(normalizePath(this.path))); + sb.append(encodePath(normalizePath(this.path, sb.length() == 0))); } if (this.encodedQuery != null) { sb.append("?").append(this.encodedQuery); @@ -166,6 +166,26 @@ private String buildString() { return sb.toString(); } + private static String normalizePath(final String path, final boolean relative) { + String s = path; + if (TextUtils.isBlank(s)) { + return ""; + } + int n = 0; + for (; n < s.length(); n++) { + if (s.charAt(n) != '/') { + break; + } + } + if (n > 1) { + s = s.substring(n - 1); + } + if (!relative && !s.startsWith("/")) { + s = "/" + s; + } + return s; + } + private void digestURI(final URI uri) { this.scheme = uri.getScheme(); this.encodedSchemeSpecificPart = uri.getRawSchemeSpecificPart(); @@ -491,24 +511,4 @@ public String toString() { return buildString(); } - private static String normalizePath(final String path) { - String s = path; - if (TextUtils.isBlank(s)) { - return ""; - } - int n = 0; - for (; n < s.length(); n++) { - if (s.charAt(n) != '/') { - break; - } - } - if (n > 1) { - s = s.substring(n - 1); - } - if (!s.startsWith("/")) { - s = "/" + s; - } - return s; - } - } diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java index 6afc594220..8bca89ef11 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java @@ -299,4 +299,16 @@ public void testMalformedPath() throws Exception { Assert.assertEquals("example.com", uri.getHost()); } + @Test + public void testRelativePath() throws Exception { + final URI uri = new URIBuilder("./mypath").build(); + Assert.assertEquals(new URI("./mypath"), uri); + } + + @Test + public void testRelativePathWithAuthority() throws Exception { + final URI uri = new URIBuilder("./mypath").setHost("somehost").setScheme("http").build(); + Assert.assertEquals(new URI("http://somehost/./mypath"), uri); + } + } From d6bfb3df9c1a4ffb4e531f2ef203594c8781fed8 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 21 Mar 2017 14:45:56 +0000 Subject: [PATCH 110/204] HTTPCLIENT-1830: await termination of the IdleConnectionEvictor when it is shut down Contributed by Liam Williams git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1787980 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/impl/client/HttpClientBuilder.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 294135d396..6baa387fd0 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -1213,6 +1213,11 @@ public CloseableHttpClient build() { @Override public void close() throws IOException { connectionEvictor.shutdown(); + try { + connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + } } }); From 2635028db0f037f21192e14960932d876ed1482c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 22 Mar 2017 08:36:35 +0000 Subject: [PATCH 111/204] HTTPCLIENT-1835: evictExpiredConnections no longer causes the evictIdleConnections behaviour to be enabled when evictIdleConnections is not explicitly enabled git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1788066 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/http/impl/client/HttpClientBuilder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 6baa387fd0..4806e387f1 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -1207,7 +1207,8 @@ public CloseableHttpClient build() { if (evictExpiredConnections || evictIdleConnections) { final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm, - maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS); + maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS, + maxIdleTime, maxIdleTimeUnit); closeablesCopy.add(new Closeable() { @Override From c5c10f5e9ecc4e0988ea0042b9bdc5072e9cf436 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 26 Mar 2017 02:26:35 +0000 Subject: [PATCH 112/204] Use final. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1788706 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/http/client/fluent/Request.java | 2 +- .../org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java | 2 +- .../test/java/org/apache/http/osgi/impl/WeakListTest.java | 2 +- .../java/org/apache/http/conn/ssl/AbstractVerifier.java | 6 +++--- .../org/apache/http/conn/ssl/DefaultHostnameVerifier.java | 2 +- .../http/impl/client/SystemDefaultCredentialsProvider.java | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java index 1d2de2e736..4c43f59395 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java @@ -353,7 +353,7 @@ public Request body(final HttpEntity entity) { public Request bodyForm(final Iterable formParams, final Charset charset) { final List paramList = new ArrayList(); - for (NameValuePair param : formParams) { + for (final NameValuePair param : formParams) { paramList.add(param); } final ContentType contentType = ContentType.create(URLEncodedUtils.CONTENT_TYPE, charset); diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java index 2af252fbcc..21e4917108 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/OSGiHttpRoutePlanner.java @@ -53,7 +53,7 @@ final class OSGiHttpRoutePlanner extends DefaultRoutePlanner { "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"); - private List proxyConfigurations; + private final List proxyConfigurations; public OSGiHttpRoutePlanner(final List proxyConfigurations) { super(null); diff --git a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java index 77770bf42d..7fc83074b3 100644 --- a/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java +++ b/httpclient-osgi/src/test/java/org/apache/http/osgi/impl/WeakListTest.java @@ -53,7 +53,7 @@ public void testWeakList() { boolean thrown = false; try { it.next(); - } catch (NoSuchElementException e) { + } catch (final NoSuchElementException e) { thrown = true; } assertTrue(thrown); diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java index ef56890e7c..37771133c6 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -136,13 +136,13 @@ public final void verify( final List allSubjectAltNames = DefaultHostnameVerifier.getSubjectAltNames(cert); final List subjectAlts = new ArrayList(); if (InetAddressUtils.isIPv4Address(host) || InetAddressUtils.isIPv6Address(host)) { - for (SubjectName subjectName: allSubjectAltNames) { + for (final SubjectName subjectName: allSubjectAltNames) { if (subjectName.getType() == SubjectName.IP) { subjectAlts.add(subjectName.getValue()); } } } else { - for (SubjectName subjectName: allSubjectAltNames) { + for (final SubjectName subjectName: allSubjectAltNames) { if (subjectName.getType() == SubjectName.DNS) { subjectAlts.add(subjectName.getValue()); } @@ -262,7 +262,7 @@ public static String[] getDNSSubjectAlts(final X509Certificate cert) { return null; } final List dnsAlts = new ArrayList(); - for (SubjectName subjectName: subjectAltNames) { + for (final SubjectName subjectName: subjectAltNames) { if (subjectName.getType() == SubjectName.DNS) { dnsAlts.add(subjectName.getValue()); } diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 2844f3b67a..1b03f220df 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -303,7 +303,7 @@ static List getSubjectAltNames(final X509Certificate cert) { return Collections.emptyList(); } final List result = new ArrayList(); - for (List entry: entries) { + for (final List entry: entries) { final Integer type = entry.size() >= 2 ? (Integer) entry.get(0) : null; if (type != null) { final String s = (String) entry.get(1); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index f6f30ccfeb..9473ab257d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -132,7 +132,7 @@ public Credentials getCredentials(final AuthScope authscope) { systemcreds = new PasswordAuthentication(proxyUser, proxyPassword != null ? proxyPassword.toCharArray() : new char[] {}); } } - } catch (NumberFormatException ex) { + } catch (final NumberFormatException ex) { } } } From 4aa07e6c519d2a3f8d4086c7e8cf494c8e939010 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 26 Mar 2017 02:28:02 +0000 Subject: [PATCH 113/204] Add missing '@Override' annotations. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1788707 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/client/cache/CachingHttpClient.java | 11 +++++++++++ .../main/java/org/apache/http/osgi/impl/WeakList.java | 3 +++ 2 files changed, 14 insertions(+) diff --git a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java index 0443ce61c1..c066eaf68a 100644 --- a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java +++ b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java @@ -339,38 +339,45 @@ public long getCacheUpdates() { return cacheUpdates.get(); } + @Override public HttpResponse execute(final HttpHost target, final HttpRequest request) throws IOException { final HttpContext defaultContext = null; return execute(target, request, defaultContext); } + @Override public T execute(final HttpHost target, final HttpRequest request, final ResponseHandler responseHandler) throws IOException { return execute(target, request, responseHandler, null); } + @Override public T execute(final HttpHost target, final HttpRequest request, final ResponseHandler responseHandler, final HttpContext context) throws IOException { final HttpResponse resp = execute(target, request, context); return handleAndConsume(responseHandler,resp); } + @Override public HttpResponse execute(final HttpUriRequest request) throws IOException { final HttpContext context = null; return execute(request, context); } + @Override public HttpResponse execute(final HttpUriRequest request, final HttpContext context) throws IOException { final URI uri = request.getURI(); final HttpHost httpHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()); return execute(httpHost, request, context); } + @Override public T execute(final HttpUriRequest request, final ResponseHandler responseHandler) throws IOException { return execute(request, responseHandler, null); } + @Override public T execute(final HttpUriRequest request, final ResponseHandler responseHandler, final HttpContext context) throws IOException { final HttpResponse resp = execute(request, context); @@ -408,14 +415,17 @@ private T handleAndConsume( return result; } + @Override public ClientConnectionManager getConnectionManager() { return backend.getConnectionManager(); } + @Override public HttpParams getParams() { return backend.getParams(); } + @Override public HttpResponse execute(final HttpHost target, final HttpRequest originalRequest, final HttpContext context) throws IOException { @@ -1138,6 +1148,7 @@ static class AsynchronousValidationRequest implements Runnable { this.identifier = identifier; } + @Override public void run() { try { cachingClient.revalidateCacheEntry(target, request, context, cacheEntry); diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java index 5325196cc7..3df063fb0f 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/WeakList.java @@ -93,10 +93,12 @@ public WeakIterator(final Iterator> innerIterator) { fetchNext(); } + @Override public boolean hasNext() { return next != null; } + @Override public T next() { if (next != null) { final T result = next.get(); @@ -119,6 +121,7 @@ private void fetchNext() { next = null; } + @Override public void remove() { throw new UnsupportedOperationException(); } From 54a2fb2662f6fe825121276d055b4e2f7864ed79 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 28 Mar 2017 15:54:03 +0000 Subject: [PATCH 114/204] Statement unnecessarily nested within else clause. --- .../http/conn/ssl/DefaultHostnameVerifier.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 1b03f220df..982674e1a4 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -284,14 +284,13 @@ static String extractCN(final String subjectPrincipal) throws SSLException { static HostNameType determineHostFormat(final String host) { if (InetAddressUtils.isIPv4Address(host)) { return HostNameType.IPv4; - } else { - String s = host; - if (s.startsWith("[") && s.endsWith("]")) { - s = host.substring(1, host.length() - 1); - } - if (InetAddressUtils.isIPv6Address(s)) { - return HostNameType.IPv6; - } + } + String s = host; + if (s.startsWith("[") && s.endsWith("]")) { + s = host.substring(1, host.length() - 1); + } + if (InetAddressUtils.isIPv6Address(s)) { + return HostNameType.IPv6; } return HostNameType.DNS; } @@ -303,7 +302,7 @@ static List getSubjectAltNames(final X509Certificate cert) { return Collections.emptyList(); } final List result = new ArrayList(); - for (final List entry: entries) { + for (final List entry : entries) { final Integer type = entry.size() >= 2 ? (Integer) entry.get(0) : null; if (type != null) { final String s = (String) entry.get(1); From c58288c9af339343a4433888a73f70669c2556ff Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 28 Mar 2017 18:50:01 +0000 Subject: [PATCH 115/204] [HTTPCLIENT-1836] DefaultHostnameVerifier#getSubjectAltNames(X509Certificate) throws java.lang.ClassCastException. Contributed by Gary Gregory , Ilian Iliev --- RELEASE_NOTES.txt | 2 ++ .../org/apache/http/conn/ssl/DefaultHostnameVerifier.java | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 95ceac3cd8..41373b9819 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -17,6 +17,8 @@ Changelog: * [HTTPCLIENT-1816] Update Apache Commons Codec 1.9 to 1.10. Contributed by Gary Gregory +* [HTTPCLIENT-1836] DefaultHostnameVerifier#getSubjectAltNames(X509Certificate) throws java.lang.ClassCastException. + Contributed by Gary Gregory , Ilian Iliev Release 4.5.3 ------------------- diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 982674e1a4..2202abe16f 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -305,8 +305,12 @@ static List getSubjectAltNames(final X509Certificate cert) { for (final List entry : entries) { final Integer type = entry.size() >= 2 ? (Integer) entry.get(0) : null; if (type != null) { - final String s = (String) entry.get(1); - result.add(new SubjectName(s, type)); + final Object o = entry.get(1); + if (o instanceof String) { + result.add(new SubjectName((String) o, type.intValue())); + } else if (o instanceof byte[]) { + // TODO ASN.1 DER encoded form + } } } return result; From 61bf8ba35ed995f7b72cccb7ffed38e28a0b8188 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 3 Apr 2017 19:04:04 +0000 Subject: [PATCH 116/204] fix cache NFE for big content length git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1790037 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/impl/client/cache/ResponseCachingPolicy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java index bbcb5d16b8..a96615301e 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java @@ -126,7 +126,7 @@ public boolean isResponseCacheable(final String httpMethod, final HttpResponse r final Header contentLength = response.getFirstHeader(HTTP.CONTENT_LEN); if (contentLength != null) { - final int contentLengthValue = Integer.parseInt(contentLength.getValue()); + final long contentLengthValue = Long.parseLong(contentLength.getValue()); if (contentLengthValue > this.maxObjectSizeBytes) { return false; } From 288a91cc54df8421b602ea129f2a096c697e8d74 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 25 Apr 2017 23:03:05 +0000 Subject: [PATCH 117/204] Replace @exception with the more modern @throws. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1792679 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/http/impl/conn/DefaultClientConnectionOperator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java index 5eaac13527..bab8b62821 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnectionOperator.java @@ -252,7 +252,7 @@ protected void prepareSocket( * * @param host host name to resolve * @return array of IP addresses - * @exception UnknownHostException if no IP address for the host could be determined. + * @throws UnknownHostException if no IP address for the host could be determined. * * @see DnsResolver * @see SystemDefaultDnsResolver From a54bee2c7e64dcbe479cbb5a37b2a9f0c8b64dd7 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 19:17:42 +0000 Subject: [PATCH 118/204] [HTTPCLIENT-1845]: Extract InputStreamFactory classes out of GzipDecompressingEntity and DeflateDecompressingEntity for reuse and to create less garbage. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1794442 13f79535-47bb-0310-9956-ffa450edef68 --- RELEASE_NOTES.txt | 4 ++ .../entity/DeflateDecompressingEntity.java | 12 +--- .../entity/DeflateInputStreamFactory.java | 63 ++++++++++++++++++ .../client/entity/GZIPInputStreamFactory.java | 64 +++++++++++++++++++ .../entity/GzipDecompressingEntity.java | 13 +--- .../protocol/ResponseContentEncoding.java | 28 ++------ 6 files changed, 138 insertions(+), 46 deletions(-) create mode 100644 httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java create mode 100644 httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 41373b9819..4380d58924 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -19,6 +19,10 @@ Changelog: * [HTTPCLIENT-1836] DefaultHostnameVerifier#getSubjectAltNames(X509Certificate) throws java.lang.ClassCastException. Contributed by Gary Gregory , Ilian Iliev + +* [HTTPCLIENT-1845]: Extract InputStreamFactory classes out of GzipDecompressingEntity and + DeflateDecompressingEntity for reuse and to create less garbage. + Contributed by Gary Gregory Release 4.5.3 ------------------- diff --git a/httpclient/src/main/java/org/apache/http/client/entity/DeflateDecompressingEntity.java b/httpclient/src/main/java/org/apache/http/client/entity/DeflateDecompressingEntity.java index 1d3cd7fe70..6551a4ba44 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/DeflateDecompressingEntity.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/DeflateDecompressingEntity.java @@ -26,9 +26,6 @@ */ package org.apache.http.client.entity; -import java.io.IOException; -import java.io.InputStream; - import org.apache.http.HttpEntity; /** @@ -57,14 +54,7 @@ public class DeflateDecompressingEntity extends DecompressingEntity { * a non-null {@link HttpEntity} to be wrapped */ public DeflateDecompressingEntity(final HttpEntity entity) { - super(entity, new InputStreamFactory() { - - @Override - public InputStream create(final InputStream instream) throws IOException { - return new DeflateInputStream(instream); - } - - }); + super(entity, DeflateInputStreamFactory.getInstance()); } } diff --git a/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java new file mode 100644 index 0000000000..3853efea0d --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java @@ -0,0 +1,63 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.entity; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; + +/** + * {@link InputStreamFactory} for handling Deflate Content Coded responses. + * + * @since 4.5.4 + */ +@Contract(threading = ThreadingBehavior.IMMUTABLE) +public class DeflateInputStreamFactory implements InputStreamFactory { + + /** + * Singleton instance. + */ + private static final DeflateInputStreamFactory INSTANCE = new DeflateInputStreamFactory(); + + /** + * Gets the singleton instance. + * + * @return the singleton instance. + */ + public static DeflateInputStreamFactory getInstance() { + return INSTANCE; + } + + @Override + public InputStream create(final InputStream inputStream) throws IOException { + return new DeflateInputStream(inputStream); + } + +} diff --git a/httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java b/httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java new file mode 100644 index 0000000000..f52fd12e8c --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java @@ -0,0 +1,64 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.entity; + +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.GZIPInputStream; + +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; + +/** + * {@link InputStreamFactory} for handling GZIPContent Coded responses. + * + * @since 4.5.4 + */ +@Contract(threading = ThreadingBehavior.IMMUTABLE) +public class GZIPInputStreamFactory implements InputStreamFactory { + + /** + * Singleton instance. + */ + private static final GZIPInputStreamFactory INSTANCE = new GZIPInputStreamFactory(); + + /** + * Gets the singleton instance. + * + * @return the singleton instance. + */ + public static GZIPInputStreamFactory getInstance() { + return INSTANCE; + } + + @Override + public InputStream create(final InputStream inputStream) throws IOException { + return new GZIPInputStream(inputStream); + } + +} diff --git a/httpclient/src/main/java/org/apache/http/client/entity/GzipDecompressingEntity.java b/httpclient/src/main/java/org/apache/http/client/entity/GzipDecompressingEntity.java index ca45b59bb8..4fa1ecc6d8 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/GzipDecompressingEntity.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/GzipDecompressingEntity.java @@ -26,10 +26,6 @@ */ package org.apache.http.client.entity; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.GZIPInputStream; - import org.apache.http.HttpEntity; /** @@ -48,14 +44,7 @@ public class GzipDecompressingEntity extends DecompressingEntity { * the non-null {@link HttpEntity} to be wrapped */ public GzipDecompressingEntity(final HttpEntity entity) { - super(entity, new InputStreamFactory() { - - @Override - public InputStream create(final InputStream instream) throws IOException { - return new GZIPInputStream(instream); - } - - }); + super(entity, GZIPInputStreamFactory.getInstance()); } } diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java index 8bb63c6572..476eb63205 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java @@ -27,9 +27,7 @@ package org.apache.http.client.protocol; import java.io.IOException; -import java.io.InputStream; import java.util.Locale; -import java.util.zip.GZIPInputStream; import org.apache.http.Header; import org.apache.http.HeaderElement; @@ -41,7 +39,8 @@ import org.apache.http.annotation.ThreadingBehavior; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.DecompressingEntity; -import org.apache.http.client.entity.DeflateInputStream; +import org.apache.http.client.entity.DeflateInputStreamFactory; +import org.apache.http.client.entity.GZIPInputStreamFactory; import org.apache.http.client.entity.InputStreamFactory; import org.apache.http.config.Lookup; import org.apache.http.config.RegistryBuilder; @@ -61,23 +60,6 @@ public class ResponseContentEncoding implements HttpResponseInterceptor { public static final String UNCOMPRESSED = "http.client.response.uncompressed"; - private final static InputStreamFactory GZIP = new InputStreamFactory() { - - @Override - public InputStream create(final InputStream instream) throws IOException { - return new GZIPInputStream(instream); - } - }; - - private final static InputStreamFactory DEFLATE = new InputStreamFactory() { - - @Override - public InputStream create(final InputStream instream) throws IOException { - return new DeflateInputStream(instream); - } - - }; - private final Lookup decoderRegistry; private final boolean ignoreUnknown; @@ -87,9 +69,9 @@ public InputStream create(final InputStream instream) throws IOException { public ResponseContentEncoding(final Lookup decoderRegistry, final boolean ignoreUnknown) { this.decoderRegistry = decoderRegistry != null ? decoderRegistry : RegistryBuilder.create() - .register("gzip", GZIP) - .register("x-gzip", GZIP) - .register("deflate", DEFLATE) + .register("gzip", GZIPInputStreamFactory.getInstance()) + .register("x-gzip", GZIPInputStreamFactory.getInstance()) + .register("deflate", DeflateInputStreamFactory.getInstance()) .build(); this.ignoreUnknown = ignoreUnknown; } From 59588a2b37c6af5346533ca64a0db96aa3112688 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 19:47:41 +0000 Subject: [PATCH 119/204] Update parent project from 7 to 8. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1794447 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8d71f15c42..b1302a9e75 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ project org.apache.httpcomponents - 7 + 8 ../project/pom.xml 4.0.0 From 7ca224e327663fbfde3e9a86f3d524dbf09b0029 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:00:56 +0000 Subject: [PATCH 120/204] [HTTPCLIENT-1847] Update Ehcache from 2.6.9 to 2.6.11. Builds like a champ on Oracle Java 6 up until the OSGi module which requires Java 7 since the Maven Bundle plugin class is compiled with Java 7. Builds like a champ on Oracle Java 7. --- RELEASE_NOTES.txt | 3 +++ pom.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 4380d58924..77b7acce60 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -24,6 +24,9 @@ Changelog: DeflateDecompressingEntity for reuse and to create less garbage. Contributed by Gary Gregory +* [HTTPCLIENT-1847] Update Ehcache from 2.6.9 to 2.6.11. + Contributed by Gary Gregory + Release 4.5.3 ------------------- diff --git a/pom.xml b/pom.xml index b1302a9e75..5c5eb3e296 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ 4.4.6 1.2 1.10 - 2.6.9 + 2.6.11 2.11.4 1.7.7 4.11 From 4c96c3c80af93e714a836a9737d7f7246a60c989 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:07:53 +0000 Subject: [PATCH 121/204] [HTTPCLIENT-1847] [HTTPCLIENT-1848] Update spymemcached from 2.11.4 to 2.12.3.. Builds like a champ on Maven 3.0.5 and Oracle Java 6 up until the OSGi module which requires Java 7 since the Maven Bundle plugin class is compiled with Java 7. Builds like a champ on Oracle Java 7 and Maven 3.5.0. --- RELEASE_NOTES.txt | 3 +++ pom.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 77b7acce60..6076c3ef01 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -27,6 +27,9 @@ Changelog: * [HTTPCLIENT-1847] Update Ehcache from 2.6.9 to 2.6.11. Contributed by Gary Gregory +* [HTTPCLIENT-1848] Update spymemcached from 2.11.4 to 2.12.3. + Contributed by Gary Gregory + Release 4.5.3 ------------------- diff --git a/pom.xml b/pom.xml index 5c5eb3e296..d46e65e267 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ 1.2 1.10 2.6.11 - 2.11.4 + 2.12.3 1.7.7 4.11 2.5.2 From 53065fb48aee4bdd9f33ffd35585b03be971711b Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:31:36 +0000 Subject: [PATCH 122/204] Add missing close() call. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1794452 13f79535-47bb-0310-9956-ffa450edef68 --- .../auth/win/TestWindowsNegotiateScheme.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java b/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java index dd7275a835..9d8f2d00dd 100644 --- a/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java +++ b/httpclient-win/src/test/java/org/apache/http/impl/auth/win/TestWindowsNegotiateScheme.java @@ -110,14 +110,17 @@ public AuthScheme create(final HttpContext context) { final CloseableHttpClient customClient = HttpClientBuilder.create() .setDefaultCredentialsProvider(credsProvider) .setDefaultAuthSchemeRegistry(authSchemeRegistry).build(); - - final HttpHost target = start(); - final HttpGet httpGet = new HttpGet("/"); - final CloseableHttpResponse response = customClient.execute(target, httpGet); try { - EntityUtils.consume(response.getEntity()); - } finally { - response.close(); + final HttpHost target = start(); + final HttpGet httpGet = new HttpGet("/"); + final CloseableHttpResponse response = customClient.execute(target, httpGet); + try { + EntityUtils.consume(response.getEntity()); + } finally { + response.close(); + } + }finally { + customClient.close(); } } From 9687283526111b75021e3e9fdceea6aed20529f4 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:32:43 +0000 Subject: [PATCH 123/204] [HTTPCLIENT-1849] Update JNA from 4.1.0 to 4.4.0. --- RELEASE_NOTES.txt | 3 +++ pom.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 6076c3ef01..640e5c2c6f 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -30,6 +30,9 @@ Changelog: * [HTTPCLIENT-1848] Update spymemcached from 2.11.4 to 2.12.3. Contributed by Gary Gregory +* [HTTPCLIENT-1849] Update JNA from 4.1.0 to 4.4.0. + Contributed by Gary Gregory + Release 4.5.3 ------------------- diff --git a/pom.xml b/pom.xml index d46e65e267..414d63dbde 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,7 @@ 4.11 2.5.2 1.8.5 - 4.1.0 + 4.4.0 1 4.4
From f302a7e7e5005b6e49ea15ce4506ceca4840a652 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:42:29 +0000 Subject: [PATCH 124/204] [HTTPCLIENT-1850] Update SLF4J from 1.7.6 to 1.7.25. --- RELEASE_NOTES.txt | 4 ++++ pom.xml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 640e5c2c6f..932e10624a 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -33,6 +33,10 @@ Changelog: * [HTTPCLIENT-1849] Update JNA from 4.1.0 to 4.4.0. Contributed by Gary Gregory +* [HTTPCLIENT-1850] Update SLF4J from 1.7.6 to 1.7.25. + Contributed by Gary Gregory + + Release 4.5.3 ------------------- diff --git a/pom.xml b/pom.xml index 414d63dbde..13f40cbec6 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 1.10 2.6.11 2.12.3 - 1.7.7 + 1.7.25 4.11 2.5.2 1.8.5 From 6f81c7ed41afbdaec364f76a1c35d18fa558d942 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:49:11 +0000 Subject: [PATCH 125/204] Update tests from Mockito 1.8.5 to 1.9.5. Tests pass on Oracle Java 1.6.0_45 and Maven 3.0.5. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1794458 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 13f40cbec6..7cf862e384 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ 1.7.25 4.11 2.5.2 - 1.8.5 + 1.9.5 4.4.0 1 4.4 From 05a547c115a429520fa0ee43c8dcf995c539d6bf Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:51:45 +0000 Subject: [PATCH 126/204] Update tests from Mockito 1.9.5 to 1.10.19. Tests pass on Oracle Java 1.6.0_45 and Maven 3.0.5. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1794459 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7cf862e384..10ca8a52f8 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ 1.7.25 4.11 2.5.2 - 1.9.5 + 1.10.19 4.4.0 1 4.4 From 38ac1e3a4602046afb7e903b98d06fa2b1fccf34 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 20:55:12 +0000 Subject: [PATCH 127/204] Remove duplication of managed version 0.11 for apache-rat-plugin. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1794460 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 10ca8a52f8..8a6f3c445f 100644 --- a/pom.xml +++ b/pom.xml @@ -368,7 +368,6 @@ org.apache.rat apache-rat-plugin - 0.11 verify From ce237ae735d70e505db19187a86cfbab895d7934 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 8 May 2017 23:55:36 +0000 Subject: [PATCH 128/204] Make this header look like the Java header. git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x@1794481 13f79535-47bb-0310-9956-ffa450edef68 --- .../resources/org/apache/http/client/version.properties | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/resources/org/apache/http/client/version.properties b/httpclient/src/main/resources/org/apache/http/client/version.properties index a57a8284fd..4ebb7079cb 100644 --- a/httpclient/src/main/resources/org/apache/http/client/version.properties +++ b/httpclient/src/main/resources/org/apache/http/client/version.properties @@ -1,4 +1,5 @@ # +# ==================================================================== # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -14,7 +15,13 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. +# ==================================================================== +# +# This software consists of voluntary contributions made by many +# individuals on behalf of the Apache Software Foundation. For more +# information on the Apache Software Foundation, please see +# . # info.module = HttpClient info.release = ${pom.version} From 90fd3936da8ed85156dd3b748563b7fbe024d43d Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 20 Mar 2017 09:39:31 +0000 Subject: [PATCH 129/204] Better handling of missing content-type header in OPTIONS with entity git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.6.x@1787697 13f79535-47bb-0310-9956-ffa450edef68 --- .../cache/RequestProtocolCompliance.java | 18 ++++++++++++++---- .../client/cache/TestProtocolDeviations.java | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java index a50dc8cacd..f8815fc761 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java @@ -32,7 +32,9 @@ import org.apache.http.Header; import org.apache.http.HeaderElement; +import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpHeaders; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; @@ -43,8 +45,8 @@ import org.apache.http.client.ClientProtocolException; import org.apache.http.client.cache.HeaderConstants; import org.apache.http.client.methods.HttpRequestWrapper; -import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.entity.ContentType; +import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicStatusLine; @@ -193,9 +195,17 @@ private void verifyOPTIONSRequestWithBodyHasContentType(final HttpRequest reques } private void addContentTypeHeaderIfMissing(final HttpEntityEnclosingRequest request) { - if (request.getEntity().getContentType() == null) { - ((AbstractHttpEntity) request.getEntity()).setContentType( - ContentType.APPLICATION_OCTET_STREAM.getMimeType()); + final HttpEntity entity = request.getEntity(); + if (entity != null && entity.getContentType() == null) { + final HttpEntityWrapper entityWrapper = new HttpEntityWrapper(entity) { + + @Override + public Header getContentType() { + return new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_OCTET_STREAM.getMimeType()); + } + + }; + request.setEntity(entityWrapper); } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java index 53d0d665e4..cdccb78a13 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java @@ -42,9 +42,9 @@ import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.client.utils.DateUtils; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.client.utils.DateUtils; import org.apache.http.impl.execchain.ClientExecChain; import org.apache.http.message.BasicHttpEntityEnclosingRequest; import org.apache.http.message.BasicHttpRequest; From 0b6adcc59895d726e7f7e781b79acaca06298c7c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 17 May 2017 14:37:06 +0200 Subject: [PATCH 130/204] Updated repository details in POM --- pom.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 8a6f3c445f..37e2ada8db 100644 --- a/pom.xml +++ b/pom.xml @@ -58,9 +58,10 @@ - scm:svn:https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x - scm:svn:https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x - https://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.5.x + scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git + scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git + https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} + 4.5.x From 10ab37b775bd4f3fdf82c84ab59fbc30b41e8197 Mon Sep 17 00:00:00 2001 From: Leandro Nunes Date: Thu, 18 May 2017 15:12:05 +0100 Subject: [PATCH 131/204] Removing unnecessary checks for cache invalidation calls. --- .../apache/http/impl/client/cache/TestCachingExec.java | 3 --- .../http/impl/client/cache/TestCachingExecChain.java | 9 --------- .../http/impl/client/cache/TestProtocolRequirements.java | 6 ------ 3 files changed, 18 deletions(-) diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java index abda62ae79..553163aa88 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java @@ -170,7 +170,6 @@ public void testRequestThatCannotBeServedFromCacheCausesBackendRequest() throws @Test public void testCacheMissCausesBackendRequest() throws Exception { mockImplMethods(CALL_BACKEND); - cacheInvalidatorWasCalled(); requestPolicyAllowsCaching(true); getCacheEntryReturns(null); getVariantCacheEntriesReturns(new HashMap()); @@ -192,7 +191,6 @@ public void testCacheMissCausesBackendRequest() throws Exception { @Test public void testUnsuitableUnvalidatableCacheEntryCausesBackendRequest() throws Exception { mockImplMethods(CALL_BACKEND); - cacheInvalidatorWasCalled(); requestPolicyAllowsCaching(true); requestIsFatallyNonCompliant(null); @@ -219,7 +217,6 @@ public void testUnsuitableUnvalidatableCacheEntryCausesBackendRequest() throws E @Test public void testUnsuitableValidatableCacheEntryCausesRevalidation() throws Exception { mockImplMethods(REVALIDATE_CACHE_ENTRY); - cacheInvalidatorWasCalled(); requestPolicyAllowsCaching(true); requestIsFatallyNonCompliant(null); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java index 852c1cad39..f2ddc6738c 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java @@ -311,7 +311,6 @@ protected void requestIsFatallyNonCompliant(final RequestProtocolError error) { @Test public void testSuitableCacheEntryDoesNotCauseBackendRequest() throws Exception { - cacheInvalidatorWasCalled(); requestPolicyAllowsCaching(true); getCacheEntryReturns(mockCacheEntry); cacheEntrySuitable(true); @@ -352,7 +351,6 @@ public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Except public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception { requestIsFatallyNonCompliant(null); - cacheInvalidatorWasCalled(); requestPolicyAllowsCaching(true); cacheEntrySuitable(true); getCacheEntryReturns(mockCacheEntry); @@ -1385,7 +1383,6 @@ public void testIfOnlyIfCachedAndEntryNotSuitableBackendNotCalled() throws Excep "must-revalidate") }); requestIsFatallyNonCompliant(null); - cacheInvalidatorWasCalled(); requestPolicyAllowsCaching(true); getCacheEntryReturns(entry); cacheEntrySuitable(false); @@ -1403,7 +1400,6 @@ public void testIfOnlyIfCachedAndEntryExistsAndIsSuitableReturnsEntry() throws E request.setHeader("Cache-Control", "only-if-cached"); requestIsFatallyNonCompliant(null); - cacheInvalidatorWasCalled(); requestPolicyAllowsCaching(true); getCacheEntryReturns(entry); cacheEntrySuitable(true); @@ -1733,11 +1729,6 @@ protected void getCacheEntryReturns(final HttpCacheEntry result) throws IOExcept expect(mockCache.getCacheEntry(eq(host), eqRequest(request))).andReturn(result); } - private void cacheInvalidatorWasCalled() throws IOException { - mockCache - .flushInvalidatedCacheEntriesFor((HttpHost) anyObject(), (HttpRequest) anyObject()); - } - protected void cacheEntryValidatable(final boolean b) { expect(mockValidityPolicy.isRevalidatable((HttpCacheEntry) anyObject())).andReturn(b) .anyTimes(); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java index 337808316e..27afcd5c4e 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java @@ -2504,8 +2504,6 @@ public void testMustReturnACacheEntryIfItCanRevalidateIt() throws Exception { notModified.setHeader("Date", DateUtils.formatDate(now)); notModified.setHeader("ETag", "\"etag\""); - mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), - eqRequest(request)); EasyMock.expect( mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))) .andReturn(entry); @@ -2551,7 +2549,6 @@ public void testMustReturnAFreshEnoughCacheEntryIfItHasIt() throws Exception { impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); replayMocks(); @@ -2599,7 +2596,6 @@ public void testMustServeAppropriateErrorOrWarningIfNoOriginCommunicationPossibl impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); EasyMock.expect( mockBackend.execute( @@ -2818,7 +2814,6 @@ public void testAgeHeaderPopulatedFromCacheEntryCurrentAge() throws Exception { impl = new CachingExec(mockBackend, mockCache, config); request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1)); - mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); EasyMock.expect(mockCache.getCacheEntry(EasyMock.eq(host), eqRequest(request))).andReturn(entry); replayMocks(); @@ -2881,7 +2876,6 @@ public void testHeuristicCacheOlderThan24HoursHasWarningAttached() throws Except final Capture cap = new Capture(); - mockCache.flushInvalidatedCacheEntriesFor(EasyMock.eq(host), eqRequest(request)); mockCache.flushInvalidatedCacheEntriesFor( EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequestWrapper.class), From dac57c57f655efb50c6bdc6bb9ba0b53e5a674a6 Mon Sep 17 00:00:00 2001 From: Leandro Nunes Date: Thu, 18 May 2017 15:55:42 +0100 Subject: [PATCH 132/204] Closes PR #77 Avoid fetching the cached entity twice on cache hit. --- .../http/impl/client/cache/CachingExec.java | 3 +-- .../impl/client/cache/TestCachingExec.java | 20 +++++++++++++++++++ .../client/cache/TestCachingExecChain.java | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java index 67f5748523..33bdbf10a3 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java @@ -263,10 +263,9 @@ public CloseableHttpResponse execute( requestCompliance.makeRequestCompliant(request); request.addHeader("Via",via); - flushEntriesInvalidatedByRequest(context.getTargetHost(), request); - if (!cacheableRequestPolicy.isServableFromCache(request)) { log.debug("Request is not servable from cache"); + flushEntriesInvalidatedByRequest(context.getTargetHost(), request); return callBackend(route, request, context, execAware); } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java index 553163aa88..5524f1e028 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExec.java @@ -402,6 +402,26 @@ public void testCallBackendMakesBackEndRequestAndHandlesResponse() throws Except verifyMocks(); } + @Test + public void testDoesNotFlushCachesOnCacheHit() throws Exception { + requestPolicyAllowsCaching(true); + requestIsFatallyNonCompliant(null); + + getCacheEntryReturns(mockCacheEntry); + doesNotFlushCache(); + cacheEntrySuitable(true); + cacheEntryValidatable(true); + + expect(mockResponseGenerator.generateResponse(isA(HttpRequestWrapper.class), isA(HttpCacheEntry.class))) + .andReturn(mockBackendResponse); + + replayMocks(); + final HttpResponse result = impl.execute(route, request, context); + verifyMocks(); + + Assert.assertSame(mockBackendResponse, result); + } + private IExpectationSetters implExpectsAnyRequestAndReturn( final CloseableHttpResponse response) throws Exception { final CloseableHttpResponse resp = impl.callBackend( diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java index f2ddc6738c..b71caf9268 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingExecChain.java @@ -1777,4 +1777,9 @@ protected void responseIsGeneratedFromCache() { .andReturn(mockCachedResponse); } + protected void doesNotFlushCache() throws IOException { + mockCache.flushInvalidatedCacheEntriesFor(isA(HttpHost.class), isA(HttpRequest.class)); + EasyMock.expectLastCall().andThrow(new AssertionError("flushInvalidatedCacheEntriesFor should not have been called")).anyTimes(); + } + } From 6d583c7d8cc41a188a190218a6489541b79cf35a Mon Sep 17 00:00:00 2001 From: Karl Wright Date: Thu, 22 Jun 2017 09:51:27 -0400 Subject: [PATCH 133/204] HTTPCLIENT-1859: Encode header name, filename appropriately --- .../http/entity/mime/FormBodyPartBuilder.java | 19 ++++++++++++-- .../entity/mime/TestFormBodyPartBuilder.java | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java b/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java index a04d9d6bc9..31c203a173 100644 --- a/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java +++ b/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java @@ -103,11 +103,11 @@ public FormBodyPart build() { if (headerCopy.getField(MIME.CONTENT_DISPOSITION) == null) { final StringBuilder buffer = new StringBuilder(); buffer.append("form-data; name=\""); - buffer.append(this.name); + buffer.append(encodeForHeader(this.name)); buffer.append("\""); if (this.body.getFilename() != null) { buffer.append("; filename=\""); - buffer.append(this.body.getFilename()); + buffer.append(encodeForHeader(this.body.getFilename())); buffer.append("\""); } headerCopy.addField(new MinimalField(MIME.CONTENT_DISPOSITION, buffer.toString())); @@ -138,4 +138,19 @@ public FormBodyPart build() { return new FormBodyPart(this.name, this.body, headerCopy); } + private static String encodeForHeader(final String headerName) { + if (headerName == null) { + return null; + } + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < headerName.length(); i++) { + final char x = headerName.charAt(i); + if (x == '"' || x == '\\' || x == '\r') { + sb.append("\\"); + } + sb.append(x); + } + return sb.toString(); + } + } diff --git a/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java b/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java index 49a6bd81e3..56dd4f9b8d 100644 --- a/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java +++ b/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java @@ -27,12 +27,14 @@ package org.apache.http.entity.mime; +import java.io.ByteArrayInputStream; import java.io.File; import java.util.Arrays; import java.util.List; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.entity.mime.content.InputStreamBody; import org.apache.http.entity.mime.content.StringBody; import org.junit.Assert; import org.junit.Test; @@ -58,6 +60,29 @@ public void testBuildBodyPartBasics() throws Exception { header.getFields()); } + @Test + public void testCharacterStuffing() throws Exception { + final FormBodyPartBuilder builder = FormBodyPartBuilder.create(); + final InputStreamBody fileBody = new InputStreamBody(new ByteArrayInputStream( + "hello world".getBytes("UTF-8")), "stuff_with \"quotes\" and \\slashes\\.bin"); + final FormBodyPart bodyPart2 = builder + .setName("yada_with \"quotes\" and \\slashes\\") + .setBody(fileBody) + .build(); + + Assert.assertNotNull(bodyPart2); + Assert.assertEquals("yada_with \"quotes\" and \\slashes\\", bodyPart2.getName()); + Assert.assertEquals(fileBody, bodyPart2.getBody()); + final Header header2 = bodyPart2.getHeader(); + Assert.assertNotNull(header2); + assertFields(Arrays.asList( + new MinimalField("Content-Disposition", "form-data; name=\"yada_with \\\"quotes\\\" " + + "and \\\\slashes\\\\\"; filename=\"stuff_with \\\"quotes\\\" and \\\\slashes\\\\.bin\""), + new MinimalField("Content-Type", "application/octet-stream"), + new MinimalField("Content-Transfer-Encoding", "binary")), + header2.getFields()); + } + @Test public void testBuildBodyPartMultipleBuilds() throws Exception { final StringBody stringBody = new StringBody("stuff", ContentType.TEXT_PLAIN); From cd2c36194f7c9358a5936cb39f17cd8f47f37675 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 12 Jul 2017 17:10:50 -0700 Subject: [PATCH 134/204] Ignore Eclipse .checkstyle file. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 81c3433707..84a1c56b77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ bin +.checkstyle .classpath .project .settings From 6156eb1f0f60caa99fe6d566fbccb8fbcfd0a14a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 12 Jul 2017 17:12:52 -0700 Subject: [PATCH 135/204] Add final modifier to private fields. --- .../src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 216f43f45c..70cbe50d4c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -770,7 +770,7 @@ static class Handle final private byte[] exportedSessionKey; private byte[] signingKey; private byte[] sealingKey; - private Cipher rc4; + private final Cipher rc4; final Mode mode; final private boolean isConnection; int sequenceNumber = 0; From 61529d1f880ce4ff371adad74da580865f2680d6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 12 Jul 2017 17:29:17 -0700 Subject: [PATCH 136/204] Checkstyle fixes: Use final and tab police. --- .../impl/client/cache/CachingHttpClient.java | 6 +- .../impl/client/cache/CacheKeyGenerator.java | 2 +- .../http/impl/client/cache/CachingExec.java | 2 +- .../client/cache/HeapResourceFactory.java | 2 +- .../memcached/MemcachedCacheEntryImpl.java | 8 +- .../impl/HttpProxyConfigurationActivator.java | 2 +- .../http/conn/ssl/AbstractVerifier.java | 2 +- .../apache/http/impl/auth/CredSspScheme.java | 2252 ++++++++--------- .../org/apache/http/impl/auth/DebugUtil.java | 192 +- .../apache/http/impl/auth/NTLMEngineImpl.java | 12 +- .../http/impl/client/HttpClientBuilder.java | 2 +- .../apache/http/impl/cookie/RFC2109Spec.java | 2 +- .../http/conn/ssl/TestHostnameVerifier.java | 2 +- .../http/impl/auth/TestNTLMEngineImpl.java | 2 +- .../apache/http/localserver/EchoHandler.java | 2 +- 15 files changed, 1245 insertions(+), 1245 deletions(-) diff --git a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java index c066eaf68a..20f54cf629 100644 --- a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java +++ b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java @@ -387,7 +387,7 @@ public T execute(final HttpUriRequest request, final ResponseHandler T handleAndConsume( final ResponseHandler responseHandler, final HttpResponse response) throws Error, IOException { - T result; + final T result; try { result = responseHandler.handleResponse(response); } catch (final Exception t) { @@ -429,7 +429,7 @@ public HttpParams getParams() { public HttpResponse execute(final HttpHost target, final HttpRequest originalRequest, final HttpContext context) throws IOException { - HttpRequestWrapper request; + final HttpRequestWrapper request; if (originalRequest instanceof HttpRequestWrapper) { request = ((HttpRequestWrapper) originalRequest); } else { @@ -693,7 +693,7 @@ private String generateViaHeader(final HttpMessage msg) { final VersionInfo vi = VersionInfo.loadVersionInfo("org.apache.http.client", getClass().getClassLoader()); final String release = (vi != null) ? vi.getRelease() : VersionInfo.UNAVAILABLE; - String value; + final String value; if ("http".equalsIgnoreCase(pv.getProtocol())) { value = String.format("%d.%d localhost (Apache-HttpClient/%s (cache))", pv.getMajor(), pv.getMinor(), release); diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java index 91ca500eb7..70df8cd04f 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheKeyGenerator.java @@ -155,7 +155,7 @@ public String getVariantKey(final HttpRequest req, final HttpCacheEntry entry) { } Collections.sort(variantHeaderNames); - StringBuilder buf; + final StringBuilder buf; try { buf = new StringBuilder("{"); boolean first = true; diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java index 33bdbf10a3..f7da4d0c98 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java @@ -527,7 +527,7 @@ private String generateViaHeader(final HttpMessage msg) { final VersionInfo vi = VersionInfo.loadVersionInfo("org.apache.http.client", getClass().getClassLoader()); final String release = (vi != null) ? vi.getRelease() : VersionInfo.UNAVAILABLE; - String value; + final String value; final int major = pv.getMajor(); final int minor = pv.getMinor(); if ("http".equalsIgnoreCase(pv.getProtocol())) { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java index 11506e24ea..8cb9a2d82a 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java @@ -68,7 +68,7 @@ public Resource generate( public Resource copy( final String requestId, final Resource resource) throws IOException { - byte[] body; + final byte[] body; if (resource instanceof HeapResource) { body = ((HeapResource) resource).getByteArray(); } else { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedCacheEntryImpl.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedCacheEntryImpl.java index e1c4e37c8a..9bc11e52bb 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedCacheEntryImpl.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/memcached/MemcachedCacheEntryImpl.java @@ -58,7 +58,7 @@ public MemcachedCacheEntryImpl() { @Override synchronized public byte[] toByteArray() { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos; + final ObjectOutputStream oos; try { oos = new ObjectOutputStream(bos); oos.writeObject(this.key); @@ -92,9 +92,9 @@ public synchronized HttpCacheEntry getHttpCacheEntry() { @Override synchronized public void set(final byte[] bytes) { final ByteArrayInputStream bis = new ByteArrayInputStream(bytes); - ObjectInputStream ois; - String s; - HttpCacheEntry entry; + final ObjectInputStream ois; + final String s; + final HttpCacheEntry entry; try { ois = new ObjectInputStream(bis); s = (String)ois.readObject(); diff --git a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java index 16d5c1bf58..4ca17f14ed 100644 --- a/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java +++ b/httpclient-osgi/src/main/java/org/apache/http/osgi/impl/HttpProxyConfigurationActivator.java @@ -155,7 +155,7 @@ public String getName() { @Override public void updated(final String pid, @SuppressWarnings("rawtypes") final Dictionary config) throws ConfigurationException { final ServiceRegistration registration = registeredConfigurations.get(pid); - OSGiProxyConfiguration proxyConfiguration; + final OSGiProxyConfiguration proxyConfiguration; if (registration == null) { proxyConfiguration = new OSGiProxyConfiguration(); diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java index 37771133c6..ec7c0bfe14 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -203,7 +203,7 @@ private static boolean matchIdentity(final String host, final String identity, f final boolean doWildcard = parts.length >= 3 && parts[0].endsWith("*") && (!strict || validCountryWildcard(parts)); if (doWildcard) { - boolean match; + final boolean match; final String firstpart = parts[0]; if (firstpart.length() > 1) { // e.g. server* final String prefix = firstpart.substring(0, firstpart.length() - 1); // e.g. server diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java index f8db658c98..9cc5fc84e4 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java @@ -1,1126 +1,1126 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.impl.auth; - - -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import javax.net.ssl.SSLEngineResult.Status; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.http.Consts; -import org.apache.http.Header; -import org.apache.http.HttpRequest; -import org.apache.http.auth.AUTH; -import org.apache.http.auth.AuthenticationException; -import org.apache.http.auth.Credentials; -import org.apache.http.auth.InvalidCredentialsException; -import org.apache.http.auth.MalformedChallengeException; -import org.apache.http.auth.NTCredentials; -import org.apache.http.message.BufferedHeader; -import org.apache.http.protocol.HttpContext; -import org.apache.http.ssl.SSLContexts; -import org.apache.http.util.CharArrayBuffer; -import org.apache.http.util.CharsetUtils; - -/** - *

- * Client implementation of the CredSSP protocol specified in [MS-CSSP]. - *

- *

- * Note: This is implementation is NOT GSS based. It should be. But there is no Java NTLM - * implementation as GSS module. Maybe the NTLMEngine can be converted to GSS and then this - * can be also switched to GSS. In fact it only works in CredSSP+NTLM case. - *

- *

- * Based on [MS-CSSP]: Credential Security Support Provider (CredSSP) Protocol (Revision 13.0, 7/14/2016). - * The implementation was inspired by Python CredSSP and NTLM implementation by Jordan Borean. - *

- */ -public class CredSspScheme extends AuthSchemeBase -{ - private static final Charset UNICODE_LITTLE_UNMARKED = CharsetUtils.lookup( "UnicodeLittleUnmarked" ); - public static final String SCHEME_NAME = "CredSSP"; - - private final Log log = LogFactory.getLog( CredSspScheme.class ); - - enum State - { - // Nothing sent, nothing received - UNINITIATED, - - // We are handshaking. Several messages are exchanged in this state - TLS_HANDSHAKE, - - // TLS handshake finished. Channel established - TLS_HANDSHAKE_FINISHED, - - // NTLM NEGOTIATE message sent (strictly speaking this should be SPNEGO) - NEGO_TOKEN_SENT, - - // NTLM CHALLENGE message received (strictly speaking this should be SPNEGO) - NEGO_TOKEN_RECEIVED, - - // NTLM AUTHENTICATE message sent together with a server public key - PUB_KEY_AUTH_SENT, - - // Server public key authentication message received - PUB_KEY_AUTH_RECEIVED, - - // Credentials message sent. Protocol exchange finished. - CREDENTIALS_SENT; - } - - private State state; - private SSLEngine sslEngine; - private NTLMEngineImpl.Type1Message type1Message; - private NTLMEngineImpl.Type2Message type2Message; - private NTLMEngineImpl.Type3Message type3Message; - private CredSspTsRequest lastReceivedTsRequest; - private NTLMEngineImpl.Handle ntlmOutgoingHandle; - private NTLMEngineImpl.Handle ntlmIncomingHandle; - private byte[] peerPublicKey; - - - public CredSspScheme() { - state = State.UNINITIATED; - } - - - @Override - public String getSchemeName() - { - return SCHEME_NAME; - } - - - @Override - public String getParameter( final String name ) - { - return null; - } - - - @Override - public String getRealm() - { - return null; - } - - - @Override - public boolean isConnectionBased() - { - return true; - } - - - private SSLEngine getSSLEngine() - { - if ( sslEngine == null ) - { - sslEngine = createSSLEngine(); - } - return sslEngine; - } - - - private SSLEngine createSSLEngine() - { - SSLContext sslContext; - try - { - sslContext = SSLContexts.custom().build(); - } - catch ( NoSuchAlgorithmException e ) - { - throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); - } - catch ( KeyManagementException e ) - { - throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); - } - - final X509TrustManager tm = new X509TrustManager() - { - - @Override - public void checkClientTrusted( final X509Certificate[] chain, final String authType ) - throws CertificateException - { - // Nothing to do. - } - - - @Override - public void checkServerTrusted( final X509Certificate[] chain, final String authType ) - throws CertificateException - { - // Nothing to do, accept all. CredSSP server is using its own certificate without any - // binding to the PKI trust chains. The public key is verified as part of the CredSSP - // protocol exchange. - } - - - @Override - public X509Certificate[] getAcceptedIssuers() - { - return null; - } - - }; - try - { - sslContext.init( null, new TrustManager[] - { tm }, null ); - } - catch ( KeyManagementException e ) - { - throw new RuntimeException( "SSL Context initialization error: " + e.getMessage(), e ); - } - final SSLEngine sslEngine = sslContext.createSSLEngine(); - sslEngine.setUseClientMode( true ); - return sslEngine; - } - - - @Override - protected void parseChallenge( final CharArrayBuffer buffer, final int beginIndex, final int endIndex ) - throws MalformedChallengeException - { - final String inputString = buffer.substringTrimmed( beginIndex, endIndex ); - - if ( inputString.isEmpty() ) - { - if ( state == State.UNINITIATED ) - { - // This is OK, just send out first message. That should start TLS handshake - } - else - { - final String msg = "Received unexpected empty input in state " + state; - log.error( msg ); - throw new MalformedChallengeException( msg ); - } - } - - if ( state == State.TLS_HANDSHAKE ) - { - unwrapHandshake( inputString ); - if ( getSSLEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ) - { - log.trace( "TLS handshake finished" ); - state = State.TLS_HANDSHAKE_FINISHED; - } - } - - if ( state == State.NEGO_TOKEN_SENT ) - { - final ByteBuffer buf = unwrap( inputString ); - state = State.NEGO_TOKEN_RECEIVED; - lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); - } - - if ( state == State.PUB_KEY_AUTH_SENT ) - { - final ByteBuffer buf = unwrap( inputString ); - state = State.PUB_KEY_AUTH_RECEIVED; - lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); - } - } - - - @Override - @Deprecated - public Header authenticate( - final Credentials credentials, - final HttpRequest request ) throws AuthenticationException - { - return authenticate( credentials, request, null ); - } - - - @Override - public Header authenticate( - final Credentials credentials, - final HttpRequest request, - final HttpContext context ) throws AuthenticationException - { - NTCredentials ntcredentials = null; - try - { - ntcredentials = ( NTCredentials ) credentials; - } - catch ( final ClassCastException e ) - { - throw new InvalidCredentialsException( - "Credentials cannot be used for CredSSP authentication: " - + credentials.getClass().getName() ); - } - - String outputString = null; - - if ( state == State.UNINITIATED ) - { - beginTlsHandshake(); - outputString = wrapHandshake(); - state = State.TLS_HANDSHAKE; - - } - else if ( state == State.TLS_HANDSHAKE ) - { - outputString = wrapHandshake(); - - } - else if ( state == State.TLS_HANDSHAKE_FINISHED ) - { - - final int ntlmFlags = getNtlmFlags(); - final ByteBuffer buf = allocateOutBuffer(); - type1Message = new NTLMEngineImpl.Type1Message( - ntcredentials.getDomain(), ntcredentials.getWorkstation(), ntlmFlags); - final byte[] ntlmNegoMessageEncoded = type1Message.getBytes(); - final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmNegoMessageEncoded ); - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.NEGO_TOKEN_SENT; - - } - else if ( state == State.NEGO_TOKEN_RECEIVED ) - { - final ByteBuffer buf = allocateOutBuffer(); - type2Message = new NTLMEngineImpl.Type2Message( - lastReceivedTsRequest.getNegoToken()); - - final Certificate peerServerCertificate = getPeerServerCertificate(); - - type3Message = new NTLMEngineImpl.Type3Message( - ntcredentials.getDomain(), - ntcredentials.getWorkstation(), - ntcredentials.getUserName(), - ntcredentials.getPassword(), - type2Message.getChallenge(), - type2Message.getFlags(), - type2Message.getTarget(), - type2Message.getTargetInfo(), - peerServerCertificate, - type1Message.getBytes(), - type2Message.getBytes()); - - final byte[] ntlmAuthenticateMessageEncoded = type3Message.getBytes(); - - final byte[] exportedSessionKey = type3Message.getExportedSessionKey(); - - ntlmOutgoingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.CLIENT, true); - ntlmIncomingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.SERVER, true); - - final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmAuthenticateMessageEncoded ); - peerPublicKey = getSubjectPublicKeyDer( peerServerCertificate.getPublicKey() ); - final byte[] pubKeyAuth = createPubKeyAuth(); - req.setPubKeyAuth( pubKeyAuth ); - - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.PUB_KEY_AUTH_SENT; - - } - else if ( state == State.PUB_KEY_AUTH_RECEIVED ) - { - verifyPubKeyAuthResponse( lastReceivedTsRequest.getPubKeyAuth() ); - final byte[] authInfo = createAuthInfo( ntcredentials ); - final CredSspTsRequest req = CredSspTsRequest.createAuthInfo( authInfo ); - - final ByteBuffer buf = allocateOutBuffer(); - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.CREDENTIALS_SENT; - } - else - { - throw new AuthenticationException( "Wrong state " + state ); - } - final CharArrayBuffer buffer = new CharArrayBuffer( 32 ); - if ( isProxy() ) - { - buffer.append( AUTH.PROXY_AUTH_RESP ); - } - else - { - buffer.append( AUTH.WWW_AUTH_RESP ); - } - buffer.append( ": CredSSP " ); - buffer.append( outputString ); - return new BufferedHeader( buffer ); - } - - - private int getNtlmFlags() - { - return NTLMEngineImpl.FLAG_REQUEST_OEM_ENCODING | - NTLMEngineImpl.FLAG_REQUEST_SIGN | - NTLMEngineImpl.FLAG_REQUEST_SEAL | - NTLMEngineImpl.FLAG_DOMAIN_PRESENT | - NTLMEngineImpl.FLAG_REQUEST_ALWAYS_SIGN | - NTLMEngineImpl.FLAG_REQUEST_NTLM2_SESSION | - NTLMEngineImpl.FLAG_TARGETINFO_PRESENT | - NTLMEngineImpl.FLAG_REQUEST_VERSION | - NTLMEngineImpl.FLAG_REQUEST_128BIT_KEY_EXCH | - NTLMEngineImpl.FLAG_REQUEST_EXPLICIT_KEY_EXCH | - NTLMEngineImpl.FLAG_REQUEST_56BIT_ENCRYPTION; - } - - - private Certificate getPeerServerCertificate() throws AuthenticationException - { - Certificate[] peerCertificates; - try - { - peerCertificates = sslEngine.getSession().getPeerCertificates(); - } - catch ( SSLPeerUnverifiedException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - for ( Certificate peerCertificate : peerCertificates ) - { - if ( !( peerCertificate instanceof X509Certificate ) ) - { - continue; - } - final X509Certificate peerX509Cerificate = ( X509Certificate ) peerCertificate; - if ( peerX509Cerificate.getBasicConstraints() != -1 ) - { - continue; - } - return peerX509Cerificate; - } - return null; - } - - - private byte[] createPubKeyAuth() throws AuthenticationException - { - return ntlmOutgoingHandle.signAndEncryptMessage( peerPublicKey ); - } - - - private void verifyPubKeyAuthResponse( final byte[] pubKeyAuthResponse ) throws AuthenticationException - { - final byte[] pubKeyReceived = ntlmIncomingHandle.decryptAndVerifySignedMessage( pubKeyAuthResponse ); - - // assert: pubKeyReceived = peerPublicKey + 1 - // The following algorithm is a bit simplified. But due to the ASN.1 encoding the first byte - // of the public key will be 0x30 we can pretty much rely on a fact that there will be no carry - if ( peerPublicKey.length != pubKeyReceived.length ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - if ( ( peerPublicKey[0] + 1 ) != pubKeyReceived[0] ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - for ( int i = 1; i < peerPublicKey.length; i++ ) - { - if ( peerPublicKey[i] != pubKeyReceived[i] ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - } - log.trace( "Received public key response is valid" ); - } - - - private byte[] createAuthInfo( final NTCredentials ntcredentials ) throws AuthenticationException - { - - final byte[] domainBytes = encodeUnicode( ntcredentials.getDomain() ); - final byte[] domainOctetStringBytesLengthBytes = encodeLength( domainBytes.length ); - final int domainNameLength = 1 + domainOctetStringBytesLengthBytes.length + domainBytes.length; - final byte[] domainNameLengthBytes = encodeLength( domainNameLength ); - - final byte[] usernameBytes = encodeUnicode( ntcredentials.getUserName() ); - final byte[] usernameOctetStringBytesLengthBytes = encodeLength( usernameBytes.length ); - final int userNameLength = 1 + usernameOctetStringBytesLengthBytes.length + usernameBytes.length; - final byte[] userNameLengthBytes = encodeLength( userNameLength ); - - final byte[] passwordBytes = encodeUnicode( ntcredentials.getPassword() ); - final byte[] passwordOctetStringBytesLengthBytes = encodeLength( passwordBytes.length ); - final int passwordLength = 1 + passwordOctetStringBytesLengthBytes.length + passwordBytes.length; - final byte[] passwordLengthBytes = encodeLength( passwordLength ); - - final int tsPasswordLength = 1 + domainNameLengthBytes.length + domainNameLength + - 1 + userNameLengthBytes.length + userNameLength + - 1 + passwordLengthBytes.length + passwordLength; - final byte[] tsPasswordLengthBytes = encodeLength( tsPasswordLength ); - final int credentialsOctetStringLength = 1 + tsPasswordLengthBytes.length + tsPasswordLength; - final byte[] credentialsOctetStringLengthBytes = encodeLength( credentialsOctetStringLength ); - final int credentialsLength = 1 + credentialsOctetStringLengthBytes.length + credentialsOctetStringLength; - final byte[] credentialsLengthBytes = encodeLength( credentialsLength ); - final int tsCredentialsLength = 5 + 1 + credentialsLengthBytes.length + credentialsLength; - final byte[] tsCredentialsLengthBytes = encodeLength( tsCredentialsLength ); - - final ByteBuffer buf = ByteBuffer.allocate( 1 + tsCredentialsLengthBytes.length + tsCredentialsLength ); - - // TSCredentials structure [MS-CSSP] section 2.2.1.2 - buf.put( ( byte ) 0x30 ); // seq - buf.put( tsCredentialsLengthBytes ); - - buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // credType tag [0] - buf.put( ( byte ) 3 ); // credType length - buf.put( ( byte ) 0x02 ); // type: INTEGER - buf.put( ( byte ) 1 ); // credType inner length - buf.put( ( byte ) 1 ); // credType value: 1 (password) - - buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // credentials tag [1] - buf.put( credentialsLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( credentialsOctetStringLengthBytes ); - - // TSPasswordCreds structure [MS-CSSP] section 2.2.1.2.1 - buf.put( ( byte ) 0x30 ); // seq - buf.put( tsPasswordLengthBytes ); - - buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // domainName tag [0] - buf.put( domainNameLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( domainOctetStringBytesLengthBytes ); - buf.put( domainBytes ); - - buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // userName tag [1] - buf.put( userNameLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( usernameOctetStringBytesLengthBytes ); - buf.put( usernameBytes ); - - buf.put( ( byte ) ( 0x02 | 0xa0 ) ); // password tag [2] - buf.put( passwordLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( passwordOctetStringBytesLengthBytes ); - buf.put( passwordBytes ); - - final byte[] authInfo = buf.array(); - try - { - return ntlmOutgoingHandle.signAndEncryptMessage( authInfo ); - } - catch ( NTLMEngineException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - } - - private final static byte[] EMPTYBUFFER = new byte[0]; - - private byte[] encodeUnicode( final String string ) - { - if (string == null) { - return EMPTYBUFFER; - } - return string.getBytes( UNICODE_LITTLE_UNMARKED ); - } - - - private byte[] getSubjectPublicKeyDer( final PublicKey publicKey ) throws AuthenticationException - { - // The publicKey.getEncoded() returns encoded SubjectPublicKeyInfo structure. But the CredSSP expects - // SubjectPublicKey subfield. I have found no easy way how to get just the SubjectPublicKey from - // java.security libraries. So let's use a primitive way and parse it out from the DER. - - try - { - final byte[] encodedPubKeyInfo = publicKey.getEncoded(); - - final ByteBuffer buf = ByteBuffer.wrap( encodedPubKeyInfo ); - getByteAndAssert( buf, 0x30, "initial sequence" ); - parseLength( buf ); - getByteAndAssert( buf, 0x30, "AlgorithmIdentifier sequence" ); - final int algIdSeqLength = parseLength( buf ); - buf.position( buf.position() + algIdSeqLength ); - getByteAndAssert( buf, 0x03, "subjectPublicKey type" ); - int subjectPublicKeyLegth = parseLength( buf ); - // There may be leading padding byte ... or whatever that is. Skip that. - final byte b = buf.get(); - if ( b == 0 ) - { - subjectPublicKeyLegth--; - } - else - { - buf.position( buf.position() - 1 ); - } - final byte[] subjectPublicKey = new byte[subjectPublicKeyLegth]; - buf.get( subjectPublicKey ); - return subjectPublicKey; - } - catch ( MalformedChallengeException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - } - - - private void beginTlsHandshake() throws AuthenticationException - { - try - { - getSSLEngine().beginHandshake(); - } - catch ( SSLException e ) - { - throw new AuthenticationException( "SSL Engine error: " + e.getMessage(), e ); - } - } - - - private ByteBuffer allocateOutBuffer() - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - return ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - } - - - private String wrapHandshake() throws AuthenticationException - { - final ByteBuffer src = allocateOutBuffer(); - src.flip(); - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - // Needs to be twice the size as there may be two wraps during handshake. - // Primitive and inefficient solution, but it works. - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() * 2 ); - while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ) - { - wrap( src, dst ); - } - dst.flip(); - return encodeBase64( dst ); - } - - - private String wrap( final ByteBuffer src ) throws AuthenticationException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() ); - wrap( src, dst ); - dst.flip(); - return encodeBase64( dst ); - } - - - private void wrap( final ByteBuffer src, final ByteBuffer dst ) throws AuthenticationException - { - final SSLEngine sslEngine = getSSLEngine(); - try - { - final SSLEngineResult engineResult = sslEngine.wrap( src, dst ); - if ( engineResult.getStatus() != Status.OK ) - { - throw new AuthenticationException( "SSL Engine error status: " + engineResult.getStatus() ); - } - } - catch ( SSLException e ) - { - throw new AuthenticationException( "SSL Engine wrap error: " + e.getMessage(), e ); - } - } - - - private void unwrapHandshake( final String inputString ) throws MalformedChallengeException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer src = decodeBase64( inputString ); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) - { - unwrap( src, dst ); - } - } - - - private ByteBuffer unwrap( final String inputString ) throws MalformedChallengeException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer src = decodeBase64( inputString ); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - unwrap( src, dst ); - dst.flip(); - return dst; - } - - - private void unwrap( final ByteBuffer src, final ByteBuffer dst ) throws MalformedChallengeException - { - - try - { - final SSLEngineResult engineResult = sslEngine.unwrap( src, dst ); - if ( engineResult.getStatus() != Status.OK ) - { - throw new MalformedChallengeException( "SSL Engine error status: " + engineResult.getStatus() ); - } - - if ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) - { - final Runnable task = sslEngine.getDelegatedTask(); - task.run(); - } - - } - catch ( SSLException e ) - { - throw new MalformedChallengeException( "SSL Engine unwrap error: " + e.getMessage(), e ); - } - } - - - private String encodeBase64( final ByteBuffer buffer ) - { - final int limit = buffer.limit(); - final byte[] bytes = new byte[limit]; - buffer.get( bytes ); - return new String(Base64.encodeBase64(bytes), Consts.ASCII); - } - - - private ByteBuffer decodeBase64( final String inputString ) - { - final byte[] inputBytes = Base64.decodeBase64(inputString.getBytes(Consts.ASCII)); - final ByteBuffer buffer = ByteBuffer.wrap( inputBytes ); - return buffer; - } - - - @Override - public boolean isComplete() - { - return state == State.CREDENTIALS_SENT; - } - - /** - * Implementation of the TsRequest structure used in CredSSP protocol. - * It is specified in [MS-CPPS] section 2.2.1. - */ - static class CredSspTsRequest - { - - private static final int VERSION = 3; - - private byte[] negoToken; - private byte[] authInfo; - private byte[] pubKeyAuth; - - - protected CredSspTsRequest() - { - super(); - } - - - public static CredSspTsRequest createNegoToken( final byte[] negoToken ) - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.negoToken = negoToken; - return req; - } - - - public static CredSspTsRequest createAuthInfo( final byte[] authInfo ) - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.authInfo = authInfo; - return req; - } - - - public static CredSspTsRequest createDecoded( final ByteBuffer buf ) throws MalformedChallengeException - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.decode( buf ); - return req; - } - - - public byte[] getNegoToken() - { - return negoToken; - } - - - public void setNegoToken( final byte[] negoToken ) - { - this.negoToken = negoToken; - } - - - public byte[] getAuthInfo() - { - return authInfo; - } - - - public void setAuthInfo( final byte[] authInfo ) - { - this.authInfo = authInfo; - } - - - public byte[] getPubKeyAuth() - { - return pubKeyAuth; - } - - - public void setPubKeyAuth( final byte[] pubKeyAuth ) - { - this.pubKeyAuth = pubKeyAuth; - } - - - public void decode( final ByteBuffer buf ) throws MalformedChallengeException - { - negoToken = null; - authInfo = null; - pubKeyAuth = null; - - getByteAndAssert( buf, 0x30, "initial sequence" ); - parseLength( buf ); - - while ( buf.hasRemaining() ) - { - final int contentTag = getAndAssertContentSpecificTag( buf, "content tag" ); - parseLength( buf ); - switch ( contentTag ) - { - case 0: - processVersion( buf ); - break; - case 1: - parseNegoTokens( buf ); - break; - case 2: - parseAuthInfo( buf ); - break; - case 3: - parsePubKeyAuth( buf ); - break; - case 4: - processErrorCode( buf ); - break; - default: - parseError( buf, "unexpected content tag " + contentTag ); - } - } - } - - - private void processVersion( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x02, "version type" ); - getLengthAndAssert( buf, 1, "version length" ); - getByteAndAssert( buf, VERSION, "wrong protocol version" ); - } - - - private void parseNegoTokens( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x30, "negoTokens sequence" ); - parseLength( buf ); - // I have seen both 0x30LL encoding and 0x30LL0x30LL encoding. Accept both. - byte bufByte = buf.get(); - if ( bufByte == 0x30 ) - { - parseLength( buf ); - bufByte = buf.get(); - } - if ( ( bufByte & 0xff ) != 0xa0 ) - { - parseError( buf, "negoTokens: wrong content-specific tag " + String.format( "%02X", bufByte ) ); - } - parseLength( buf ); - getByteAndAssert( buf, 0x04, "negoToken type" ); - - final int tokenLength = parseLength( buf ); - negoToken = new byte[tokenLength]; - buf.get( negoToken ); - } - - - private void parseAuthInfo( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x04, "authInfo type" ); - final int length = parseLength( buf ); - authInfo = new byte[length]; - buf.get( authInfo ); - } - - - private void parsePubKeyAuth( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x04, "pubKeyAuth type" ); - final int length = parseLength( buf ); - pubKeyAuth = new byte[length]; - buf.get( pubKeyAuth ); - } - - - private void processErrorCode( final ByteBuffer buf ) throws MalformedChallengeException - { - getLengthAndAssert( buf, 3, "error code length" ); - getByteAndAssert( buf, 0x02, "error code type" ); - getLengthAndAssert( buf, 1, "error code length" ); - final byte errorCode = buf.get(); - parseError( buf, "Error code " + errorCode ); - } - - - public void encode( final ByteBuffer buf ) - { - final ByteBuffer inner = ByteBuffer.allocate( buf.capacity() ); - - // version tag [0] - inner.put( ( byte ) ( 0x00 | 0xa0 ) ); - inner.put( ( byte ) 3 ); // length - - inner.put( ( byte ) ( 0x02 ) ); // INTEGER tag - inner.put( ( byte ) 1 ); // length - inner.put( ( byte ) VERSION ); // value - - if ( negoToken != null ) - { - int len = negoToken.length; - final byte[] negoTokenLengthBytes = encodeLength( len ); - len += 1 + negoTokenLengthBytes.length; - final byte[] negoTokenLength1Bytes = encodeLength( len ); - len += 1 + negoTokenLength1Bytes.length; - final byte[] negoTokenLength2Bytes = encodeLength( len ); - len += 1 + negoTokenLength2Bytes.length; - final byte[] negoTokenLength3Bytes = encodeLength( len ); - len += 1 + negoTokenLength3Bytes.length; - final byte[] negoTokenLength4Bytes = encodeLength( len ); - - inner.put( ( byte ) ( 0x01 | 0xa0 ) ); // negoData tag [1] - inner.put( negoTokenLength4Bytes ); // length - - inner.put( ( byte ) ( 0x30 ) ); // SEQUENCE tag - inner.put( negoTokenLength3Bytes ); // length - - inner.put( ( byte ) ( 0x30 ) ); // .. of SEQUENCE tag - inner.put( negoTokenLength2Bytes ); // length - - inner.put( ( byte ) ( 0x00 | 0xa0 ) ); // negoToken tag [0] - inner.put( negoTokenLength1Bytes ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( negoTokenLengthBytes ); // length - - inner.put( negoToken ); - } - - if ( authInfo != null ) - { - final byte[] authInfoEncodedLength = encodeLength( authInfo.length ); - - inner.put( ( byte ) ( 0x02 | 0xa0 ) ); // authInfo tag [2] - inner.put( encodeLength( 1 + authInfoEncodedLength.length + authInfo.length ) ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( authInfoEncodedLength ); - inner.put( authInfo ); - } - - if ( pubKeyAuth != null ) - { - final byte[] pubKeyAuthEncodedLength = encodeLength( pubKeyAuth.length ); - - inner.put( ( byte ) ( 0x03 | 0xa0 ) ); // pubKeyAuth tag [3] - inner.put( encodeLength( 1 + pubKeyAuthEncodedLength.length + pubKeyAuth.length ) ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( pubKeyAuthEncodedLength ); - inner.put( pubKeyAuth ); - } - - inner.flip(); - - // SEQUENCE tag - buf.put( ( byte ) ( 0x10 | 0x20 ) ); - buf.put( encodeLength( inner.limit() ) ); - buf.put( inner ); - } - - - public String debugDump() - { - final StringBuilder sb = new StringBuilder( "TsRequest\n" ); - sb.append( " negoToken:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, negoToken ); - sb.append( "\n" ); - sb.append( " authInfo:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, authInfo ); - sb.append( "\n" ); - sb.append( " pubKeyAuth:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, pubKeyAuth ); - return sb.toString(); - } - - - @Override - public String toString() - { - return "TsRequest(negoToken=" + Arrays.toString( negoToken ) + ", authInfo=" - + Arrays.toString( authInfo ) + ", pubKeyAuth=" + Arrays.toString( pubKeyAuth ) + ")"; - } - } - - static void getByteAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) - throws MalformedChallengeException - { - final byte bufByte = buf.get(); - if ( bufByte != expectedValue ) - { - parseError( buf, errorMessage + expectMessage( expectedValue, bufByte ) ); - } - } - - private static String expectMessage( final int expectedValue, final int realValue ) - { - return "(expected " + String.format( "%02X", expectedValue ) + ", got " + String.format( "%02X", realValue ) - + ")"; - } - - static int parseLength( final ByteBuffer buf ) - { - byte bufByte = buf.get(); - if ( bufByte == 0x80 ) - { - return -1; // infinite - } - if ( ( bufByte & 0x80 ) == 0x80 ) - { - final int size = bufByte & 0x7f; - int length = 0; - for ( int i = 0; i < size; i++ ) - { - bufByte = buf.get(); - length = ( length << 8 ) + ( bufByte & 0xff ); - } - return length; - } - else - { - return bufByte; - } - } - - static void getLengthAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) - throws MalformedChallengeException - { - final int bufLength = parseLength( buf ); - if ( expectedValue != bufLength ) - { - parseError( buf, errorMessage + expectMessage( expectedValue, bufLength ) ); - } - } - - static int getAndAssertContentSpecificTag( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException - { - final byte bufByte = buf.get(); - if ( ( bufByte & 0xe0 ) != 0xa0 ) - { - parseError( buf, errorMessage + ": wrong content-specific tag " + String.format( "%02X", bufByte ) ); - } - final int tag = bufByte & 0x1f; - return tag; - } - - static void parseError( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException - { - throw new MalformedChallengeException( - "Error parsing TsRequest (position:" + buf.position() + "): " + errorMessage ); - } - - static byte[] encodeLength( final int length ) - { - if ( length < 128 ) - { - final byte[] encoded = new byte[1]; - encoded[0] = ( byte ) length; - return encoded; - } - - int size = 1; - - int val = length; - while ( ( val >>>= 8 ) != 0 ) - { - size++; - } - - final byte[] encoded = new byte[1 + size]; - encoded[0] = ( byte ) ( size | 0x80 ); - - int shift = ( size - 1 ) * 8; - for ( int i = 0; i < size; i++ ) - { - encoded[i + 1] = ( byte ) ( length >> shift ); - shift -= 8; - } - - return encoded; - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.auth; + + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.Consts; +import org.apache.http.Header; +import org.apache.http.HttpRequest; +import org.apache.http.auth.AUTH; +import org.apache.http.auth.AuthenticationException; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.InvalidCredentialsException; +import org.apache.http.auth.MalformedChallengeException; +import org.apache.http.auth.NTCredentials; +import org.apache.http.message.BufferedHeader; +import org.apache.http.protocol.HttpContext; +import org.apache.http.ssl.SSLContexts; +import org.apache.http.util.CharArrayBuffer; +import org.apache.http.util.CharsetUtils; + +/** + *

+ * Client implementation of the CredSSP protocol specified in [MS-CSSP]. + *

+ *

+ * Note: This is implementation is NOT GSS based. It should be. But there is no Java NTLM + * implementation as GSS module. Maybe the NTLMEngine can be converted to GSS and then this + * can be also switched to GSS. In fact it only works in CredSSP+NTLM case. + *

+ *

+ * Based on [MS-CSSP]: Credential Security Support Provider (CredSSP) Protocol (Revision 13.0, 7/14/2016). + * The implementation was inspired by Python CredSSP and NTLM implementation by Jordan Borean. + *

+ */ +public class CredSspScheme extends AuthSchemeBase +{ + private static final Charset UNICODE_LITTLE_UNMARKED = CharsetUtils.lookup( "UnicodeLittleUnmarked" ); + public static final String SCHEME_NAME = "CredSSP"; + + private final Log log = LogFactory.getLog( CredSspScheme.class ); + + enum State + { + // Nothing sent, nothing received + UNINITIATED, + + // We are handshaking. Several messages are exchanged in this state + TLS_HANDSHAKE, + + // TLS handshake finished. Channel established + TLS_HANDSHAKE_FINISHED, + + // NTLM NEGOTIATE message sent (strictly speaking this should be SPNEGO) + NEGO_TOKEN_SENT, + + // NTLM CHALLENGE message received (strictly speaking this should be SPNEGO) + NEGO_TOKEN_RECEIVED, + + // NTLM AUTHENTICATE message sent together with a server public key + PUB_KEY_AUTH_SENT, + + // Server public key authentication message received + PUB_KEY_AUTH_RECEIVED, + + // Credentials message sent. Protocol exchange finished. + CREDENTIALS_SENT; + } + + private State state; + private SSLEngine sslEngine; + private NTLMEngineImpl.Type1Message type1Message; + private NTLMEngineImpl.Type2Message type2Message; + private NTLMEngineImpl.Type3Message type3Message; + private CredSspTsRequest lastReceivedTsRequest; + private NTLMEngineImpl.Handle ntlmOutgoingHandle; + private NTLMEngineImpl.Handle ntlmIncomingHandle; + private byte[] peerPublicKey; + + + public CredSspScheme() { + state = State.UNINITIATED; + } + + + @Override + public String getSchemeName() + { + return SCHEME_NAME; + } + + + @Override + public String getParameter( final String name ) + { + return null; + } + + + @Override + public String getRealm() + { + return null; + } + + + @Override + public boolean isConnectionBased() + { + return true; + } + + + private SSLEngine getSSLEngine() + { + if ( sslEngine == null ) + { + sslEngine = createSSLEngine(); + } + return sslEngine; + } + + + private SSLEngine createSSLEngine() + { + final SSLContext sslContext; + try + { + sslContext = SSLContexts.custom().build(); + } + catch ( final NoSuchAlgorithmException e ) + { + throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); + } + catch ( final KeyManagementException e ) + { + throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); + } + + final X509TrustManager tm = new X509TrustManager() + { + + @Override + public void checkClientTrusted( final X509Certificate[] chain, final String authType ) + throws CertificateException + { + // Nothing to do. + } + + + @Override + public void checkServerTrusted( final X509Certificate[] chain, final String authType ) + throws CertificateException + { + // Nothing to do, accept all. CredSSP server is using its own certificate without any + // binding to the PKI trust chains. The public key is verified as part of the CredSSP + // protocol exchange. + } + + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return null; + } + + }; + try + { + sslContext.init( null, new TrustManager[] + { tm }, null ); + } + catch ( final KeyManagementException e ) + { + throw new RuntimeException( "SSL Context initialization error: " + e.getMessage(), e ); + } + final SSLEngine sslEngine = sslContext.createSSLEngine(); + sslEngine.setUseClientMode( true ); + return sslEngine; + } + + + @Override + protected void parseChallenge( final CharArrayBuffer buffer, final int beginIndex, final int endIndex ) + throws MalformedChallengeException + { + final String inputString = buffer.substringTrimmed( beginIndex, endIndex ); + + if ( inputString.isEmpty() ) + { + if ( state == State.UNINITIATED ) + { + // This is OK, just send out first message. That should start TLS handshake + } + else + { + final String msg = "Received unexpected empty input in state " + state; + log.error( msg ); + throw new MalformedChallengeException( msg ); + } + } + + if ( state == State.TLS_HANDSHAKE ) + { + unwrapHandshake( inputString ); + if ( getSSLEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ) + { + log.trace( "TLS handshake finished" ); + state = State.TLS_HANDSHAKE_FINISHED; + } + } + + if ( state == State.NEGO_TOKEN_SENT ) + { + final ByteBuffer buf = unwrap( inputString ); + state = State.NEGO_TOKEN_RECEIVED; + lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); + } + + if ( state == State.PUB_KEY_AUTH_SENT ) + { + final ByteBuffer buf = unwrap( inputString ); + state = State.PUB_KEY_AUTH_RECEIVED; + lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); + } + } + + + @Override + @Deprecated + public Header authenticate( + final Credentials credentials, + final HttpRequest request ) throws AuthenticationException + { + return authenticate( credentials, request, null ); + } + + + @Override + public Header authenticate( + final Credentials credentials, + final HttpRequest request, + final HttpContext context ) throws AuthenticationException + { + NTCredentials ntcredentials = null; + try + { + ntcredentials = ( NTCredentials ) credentials; + } + catch ( final ClassCastException e ) + { + throw new InvalidCredentialsException( + "Credentials cannot be used for CredSSP authentication: " + + credentials.getClass().getName() ); + } + + String outputString = null; + + if ( state == State.UNINITIATED ) + { + beginTlsHandshake(); + outputString = wrapHandshake(); + state = State.TLS_HANDSHAKE; + + } + else if ( state == State.TLS_HANDSHAKE ) + { + outputString = wrapHandshake(); + + } + else if ( state == State.TLS_HANDSHAKE_FINISHED ) + { + + final int ntlmFlags = getNtlmFlags(); + final ByteBuffer buf = allocateOutBuffer(); + type1Message = new NTLMEngineImpl.Type1Message( + ntcredentials.getDomain(), ntcredentials.getWorkstation(), ntlmFlags); + final byte[] ntlmNegoMessageEncoded = type1Message.getBytes(); + final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmNegoMessageEncoded ); + req.encode( buf ); + buf.flip(); + outputString = wrap( buf ); + state = State.NEGO_TOKEN_SENT; + + } + else if ( state == State.NEGO_TOKEN_RECEIVED ) + { + final ByteBuffer buf = allocateOutBuffer(); + type2Message = new NTLMEngineImpl.Type2Message( + lastReceivedTsRequest.getNegoToken()); + + final Certificate peerServerCertificate = getPeerServerCertificate(); + + type3Message = new NTLMEngineImpl.Type3Message( + ntcredentials.getDomain(), + ntcredentials.getWorkstation(), + ntcredentials.getUserName(), + ntcredentials.getPassword(), + type2Message.getChallenge(), + type2Message.getFlags(), + type2Message.getTarget(), + type2Message.getTargetInfo(), + peerServerCertificate, + type1Message.getBytes(), + type2Message.getBytes()); + + final byte[] ntlmAuthenticateMessageEncoded = type3Message.getBytes(); + + final byte[] exportedSessionKey = type3Message.getExportedSessionKey(); + + ntlmOutgoingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.CLIENT, true); + ntlmIncomingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.SERVER, true); + + final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmAuthenticateMessageEncoded ); + peerPublicKey = getSubjectPublicKeyDer( peerServerCertificate.getPublicKey() ); + final byte[] pubKeyAuth = createPubKeyAuth(); + req.setPubKeyAuth( pubKeyAuth ); + + req.encode( buf ); + buf.flip(); + outputString = wrap( buf ); + state = State.PUB_KEY_AUTH_SENT; + + } + else if ( state == State.PUB_KEY_AUTH_RECEIVED ) + { + verifyPubKeyAuthResponse( lastReceivedTsRequest.getPubKeyAuth() ); + final byte[] authInfo = createAuthInfo( ntcredentials ); + final CredSspTsRequest req = CredSspTsRequest.createAuthInfo( authInfo ); + + final ByteBuffer buf = allocateOutBuffer(); + req.encode( buf ); + buf.flip(); + outputString = wrap( buf ); + state = State.CREDENTIALS_SENT; + } + else + { + throw new AuthenticationException( "Wrong state " + state ); + } + final CharArrayBuffer buffer = new CharArrayBuffer( 32 ); + if ( isProxy() ) + { + buffer.append( AUTH.PROXY_AUTH_RESP ); + } + else + { + buffer.append( AUTH.WWW_AUTH_RESP ); + } + buffer.append( ": CredSSP " ); + buffer.append( outputString ); + return new BufferedHeader( buffer ); + } + + + private int getNtlmFlags() + { + return NTLMEngineImpl.FLAG_REQUEST_OEM_ENCODING | + NTLMEngineImpl.FLAG_REQUEST_SIGN | + NTLMEngineImpl.FLAG_REQUEST_SEAL | + NTLMEngineImpl.FLAG_DOMAIN_PRESENT | + NTLMEngineImpl.FLAG_REQUEST_ALWAYS_SIGN | + NTLMEngineImpl.FLAG_REQUEST_NTLM2_SESSION | + NTLMEngineImpl.FLAG_TARGETINFO_PRESENT | + NTLMEngineImpl.FLAG_REQUEST_VERSION | + NTLMEngineImpl.FLAG_REQUEST_128BIT_KEY_EXCH | + NTLMEngineImpl.FLAG_REQUEST_EXPLICIT_KEY_EXCH | + NTLMEngineImpl.FLAG_REQUEST_56BIT_ENCRYPTION; + } + + + private Certificate getPeerServerCertificate() throws AuthenticationException + { + final Certificate[] peerCertificates; + try + { + peerCertificates = sslEngine.getSession().getPeerCertificates(); + } + catch ( final SSLPeerUnverifiedException e ) + { + throw new AuthenticationException( e.getMessage(), e ); + } + for ( final Certificate peerCertificate : peerCertificates ) + { + if ( !( peerCertificate instanceof X509Certificate ) ) + { + continue; + } + final X509Certificate peerX509Cerificate = ( X509Certificate ) peerCertificate; + if ( peerX509Cerificate.getBasicConstraints() != -1 ) + { + continue; + } + return peerX509Cerificate; + } + return null; + } + + + private byte[] createPubKeyAuth() throws AuthenticationException + { + return ntlmOutgoingHandle.signAndEncryptMessage( peerPublicKey ); + } + + + private void verifyPubKeyAuthResponse( final byte[] pubKeyAuthResponse ) throws AuthenticationException + { + final byte[] pubKeyReceived = ntlmIncomingHandle.decryptAndVerifySignedMessage( pubKeyAuthResponse ); + + // assert: pubKeyReceived = peerPublicKey + 1 + // The following algorithm is a bit simplified. But due to the ASN.1 encoding the first byte + // of the public key will be 0x30 we can pretty much rely on a fact that there will be no carry + if ( peerPublicKey.length != pubKeyReceived.length ) + { + throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); + } + if ( ( peerPublicKey[0] + 1 ) != pubKeyReceived[0] ) + { + throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); + } + for ( int i = 1; i < peerPublicKey.length; i++ ) + { + if ( peerPublicKey[i] != pubKeyReceived[i] ) + { + throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); + } + } + log.trace( "Received public key response is valid" ); + } + + + private byte[] createAuthInfo( final NTCredentials ntcredentials ) throws AuthenticationException + { + + final byte[] domainBytes = encodeUnicode( ntcredentials.getDomain() ); + final byte[] domainOctetStringBytesLengthBytes = encodeLength( domainBytes.length ); + final int domainNameLength = 1 + domainOctetStringBytesLengthBytes.length + domainBytes.length; + final byte[] domainNameLengthBytes = encodeLength( domainNameLength ); + + final byte[] usernameBytes = encodeUnicode( ntcredentials.getUserName() ); + final byte[] usernameOctetStringBytesLengthBytes = encodeLength( usernameBytes.length ); + final int userNameLength = 1 + usernameOctetStringBytesLengthBytes.length + usernameBytes.length; + final byte[] userNameLengthBytes = encodeLength( userNameLength ); + + final byte[] passwordBytes = encodeUnicode( ntcredentials.getPassword() ); + final byte[] passwordOctetStringBytesLengthBytes = encodeLength( passwordBytes.length ); + final int passwordLength = 1 + passwordOctetStringBytesLengthBytes.length + passwordBytes.length; + final byte[] passwordLengthBytes = encodeLength( passwordLength ); + + final int tsPasswordLength = 1 + domainNameLengthBytes.length + domainNameLength + + 1 + userNameLengthBytes.length + userNameLength + + 1 + passwordLengthBytes.length + passwordLength; + final byte[] tsPasswordLengthBytes = encodeLength( tsPasswordLength ); + final int credentialsOctetStringLength = 1 + tsPasswordLengthBytes.length + tsPasswordLength; + final byte[] credentialsOctetStringLengthBytes = encodeLength( credentialsOctetStringLength ); + final int credentialsLength = 1 + credentialsOctetStringLengthBytes.length + credentialsOctetStringLength; + final byte[] credentialsLengthBytes = encodeLength( credentialsLength ); + final int tsCredentialsLength = 5 + 1 + credentialsLengthBytes.length + credentialsLength; + final byte[] tsCredentialsLengthBytes = encodeLength( tsCredentialsLength ); + + final ByteBuffer buf = ByteBuffer.allocate( 1 + tsCredentialsLengthBytes.length + tsCredentialsLength ); + + // TSCredentials structure [MS-CSSP] section 2.2.1.2 + buf.put( ( byte ) 0x30 ); // seq + buf.put( tsCredentialsLengthBytes ); + + buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // credType tag [0] + buf.put( ( byte ) 3 ); // credType length + buf.put( ( byte ) 0x02 ); // type: INTEGER + buf.put( ( byte ) 1 ); // credType inner length + buf.put( ( byte ) 1 ); // credType value: 1 (password) + + buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // credentials tag [1] + buf.put( credentialsLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( credentialsOctetStringLengthBytes ); + + // TSPasswordCreds structure [MS-CSSP] section 2.2.1.2.1 + buf.put( ( byte ) 0x30 ); // seq + buf.put( tsPasswordLengthBytes ); + + buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // domainName tag [0] + buf.put( domainNameLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( domainOctetStringBytesLengthBytes ); + buf.put( domainBytes ); + + buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // userName tag [1] + buf.put( userNameLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( usernameOctetStringBytesLengthBytes ); + buf.put( usernameBytes ); + + buf.put( ( byte ) ( 0x02 | 0xa0 ) ); // password tag [2] + buf.put( passwordLengthBytes ); + buf.put( ( byte ) 0x04 ); // type: OCTET STRING + buf.put( passwordOctetStringBytesLengthBytes ); + buf.put( passwordBytes ); + + final byte[] authInfo = buf.array(); + try + { + return ntlmOutgoingHandle.signAndEncryptMessage( authInfo ); + } + catch ( final NTLMEngineException e ) + { + throw new AuthenticationException( e.getMessage(), e ); + } + } + + private final static byte[] EMPTYBUFFER = new byte[0]; + + private byte[] encodeUnicode( final String string ) + { + if (string == null) { + return EMPTYBUFFER; + } + return string.getBytes( UNICODE_LITTLE_UNMARKED ); + } + + + private byte[] getSubjectPublicKeyDer( final PublicKey publicKey ) throws AuthenticationException + { + // The publicKey.getEncoded() returns encoded SubjectPublicKeyInfo structure. But the CredSSP expects + // SubjectPublicKey subfield. I have found no easy way how to get just the SubjectPublicKey from + // java.security libraries. So let's use a primitive way and parse it out from the DER. + + try + { + final byte[] encodedPubKeyInfo = publicKey.getEncoded(); + + final ByteBuffer buf = ByteBuffer.wrap( encodedPubKeyInfo ); + getByteAndAssert( buf, 0x30, "initial sequence" ); + parseLength( buf ); + getByteAndAssert( buf, 0x30, "AlgorithmIdentifier sequence" ); + final int algIdSeqLength = parseLength( buf ); + buf.position( buf.position() + algIdSeqLength ); + getByteAndAssert( buf, 0x03, "subjectPublicKey type" ); + int subjectPublicKeyLegth = parseLength( buf ); + // There may be leading padding byte ... or whatever that is. Skip that. + final byte b = buf.get(); + if ( b == 0 ) + { + subjectPublicKeyLegth--; + } + else + { + buf.position( buf.position() - 1 ); + } + final byte[] subjectPublicKey = new byte[subjectPublicKeyLegth]; + buf.get( subjectPublicKey ); + return subjectPublicKey; + } + catch ( final MalformedChallengeException e ) + { + throw new AuthenticationException( e.getMessage(), e ); + } + } + + + private void beginTlsHandshake() throws AuthenticationException + { + try + { + getSSLEngine().beginHandshake(); + } + catch ( final SSLException e ) + { + throw new AuthenticationException( "SSL Engine error: " + e.getMessage(), e ); + } + } + + + private ByteBuffer allocateOutBuffer() + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + return ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); + } + + + private String wrapHandshake() throws AuthenticationException + { + final ByteBuffer src = allocateOutBuffer(); + src.flip(); + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + // Needs to be twice the size as there may be two wraps during handshake. + // Primitive and inefficient solution, but it works. + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() * 2 ); + while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ) + { + wrap( src, dst ); + } + dst.flip(); + return encodeBase64( dst ); + } + + + private String wrap( final ByteBuffer src ) throws AuthenticationException + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() ); + wrap( src, dst ); + dst.flip(); + return encodeBase64( dst ); + } + + + private void wrap( final ByteBuffer src, final ByteBuffer dst ) throws AuthenticationException + { + final SSLEngine sslEngine = getSSLEngine(); + try + { + final SSLEngineResult engineResult = sslEngine.wrap( src, dst ); + if ( engineResult.getStatus() != Status.OK ) + { + throw new AuthenticationException( "SSL Engine error status: " + engineResult.getStatus() ); + } + } + catch ( final SSLException e ) + { + throw new AuthenticationException( "SSL Engine wrap error: " + e.getMessage(), e ); + } + } + + + private void unwrapHandshake( final String inputString ) throws MalformedChallengeException + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + final ByteBuffer src = decodeBase64( inputString ); + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); + while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) + { + unwrap( src, dst ); + } + } + + + private ByteBuffer unwrap( final String inputString ) throws MalformedChallengeException + { + final SSLEngine sslEngine = getSSLEngine(); + final SSLSession sslSession = sslEngine.getSession(); + final ByteBuffer src = decodeBase64( inputString ); + final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); + unwrap( src, dst ); + dst.flip(); + return dst; + } + + + private void unwrap( final ByteBuffer src, final ByteBuffer dst ) throws MalformedChallengeException + { + + try + { + final SSLEngineResult engineResult = sslEngine.unwrap( src, dst ); + if ( engineResult.getStatus() != Status.OK ) + { + throw new MalformedChallengeException( "SSL Engine error status: " + engineResult.getStatus() ); + } + + if ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) + { + final Runnable task = sslEngine.getDelegatedTask(); + task.run(); + } + + } + catch ( final SSLException e ) + { + throw new MalformedChallengeException( "SSL Engine unwrap error: " + e.getMessage(), e ); + } + } + + + private String encodeBase64( final ByteBuffer buffer ) + { + final int limit = buffer.limit(); + final byte[] bytes = new byte[limit]; + buffer.get( bytes ); + return new String(Base64.encodeBase64(bytes), Consts.ASCII); + } + + + private ByteBuffer decodeBase64( final String inputString ) + { + final byte[] inputBytes = Base64.decodeBase64(inputString.getBytes(Consts.ASCII)); + final ByteBuffer buffer = ByteBuffer.wrap( inputBytes ); + return buffer; + } + + + @Override + public boolean isComplete() + { + return state == State.CREDENTIALS_SENT; + } + + /** + * Implementation of the TsRequest structure used in CredSSP protocol. + * It is specified in [MS-CPPS] section 2.2.1. + */ + static class CredSspTsRequest + { + + private static final int VERSION = 3; + + private byte[] negoToken; + private byte[] authInfo; + private byte[] pubKeyAuth; + + + protected CredSspTsRequest() + { + super(); + } + + + public static CredSspTsRequest createNegoToken( final byte[] negoToken ) + { + final CredSspTsRequest req = new CredSspTsRequest(); + req.negoToken = negoToken; + return req; + } + + + public static CredSspTsRequest createAuthInfo( final byte[] authInfo ) + { + final CredSspTsRequest req = new CredSspTsRequest(); + req.authInfo = authInfo; + return req; + } + + + public static CredSspTsRequest createDecoded( final ByteBuffer buf ) throws MalformedChallengeException + { + final CredSspTsRequest req = new CredSspTsRequest(); + req.decode( buf ); + return req; + } + + + public byte[] getNegoToken() + { + return negoToken; + } + + + public void setNegoToken( final byte[] negoToken ) + { + this.negoToken = negoToken; + } + + + public byte[] getAuthInfo() + { + return authInfo; + } + + + public void setAuthInfo( final byte[] authInfo ) + { + this.authInfo = authInfo; + } + + + public byte[] getPubKeyAuth() + { + return pubKeyAuth; + } + + + public void setPubKeyAuth( final byte[] pubKeyAuth ) + { + this.pubKeyAuth = pubKeyAuth; + } + + + public void decode( final ByteBuffer buf ) throws MalformedChallengeException + { + negoToken = null; + authInfo = null; + pubKeyAuth = null; + + getByteAndAssert( buf, 0x30, "initial sequence" ); + parseLength( buf ); + + while ( buf.hasRemaining() ) + { + final int contentTag = getAndAssertContentSpecificTag( buf, "content tag" ); + parseLength( buf ); + switch ( contentTag ) + { + case 0: + processVersion( buf ); + break; + case 1: + parseNegoTokens( buf ); + break; + case 2: + parseAuthInfo( buf ); + break; + case 3: + parsePubKeyAuth( buf ); + break; + case 4: + processErrorCode( buf ); + break; + default: + parseError( buf, "unexpected content tag " + contentTag ); + } + } + } + + + private void processVersion( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x02, "version type" ); + getLengthAndAssert( buf, 1, "version length" ); + getByteAndAssert( buf, VERSION, "wrong protocol version" ); + } + + + private void parseNegoTokens( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x30, "negoTokens sequence" ); + parseLength( buf ); + // I have seen both 0x30LL encoding and 0x30LL0x30LL encoding. Accept both. + byte bufByte = buf.get(); + if ( bufByte == 0x30 ) + { + parseLength( buf ); + bufByte = buf.get(); + } + if ( ( bufByte & 0xff ) != 0xa0 ) + { + parseError( buf, "negoTokens: wrong content-specific tag " + String.format( "%02X", bufByte ) ); + } + parseLength( buf ); + getByteAndAssert( buf, 0x04, "negoToken type" ); + + final int tokenLength = parseLength( buf ); + negoToken = new byte[tokenLength]; + buf.get( negoToken ); + } + + + private void parseAuthInfo( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x04, "authInfo type" ); + final int length = parseLength( buf ); + authInfo = new byte[length]; + buf.get( authInfo ); + } + + + private void parsePubKeyAuth( final ByteBuffer buf ) throws MalformedChallengeException + { + getByteAndAssert( buf, 0x04, "pubKeyAuth type" ); + final int length = parseLength( buf ); + pubKeyAuth = new byte[length]; + buf.get( pubKeyAuth ); + } + + + private void processErrorCode( final ByteBuffer buf ) throws MalformedChallengeException + { + getLengthAndAssert( buf, 3, "error code length" ); + getByteAndAssert( buf, 0x02, "error code type" ); + getLengthAndAssert( buf, 1, "error code length" ); + final byte errorCode = buf.get(); + parseError( buf, "Error code " + errorCode ); + } + + + public void encode( final ByteBuffer buf ) + { + final ByteBuffer inner = ByteBuffer.allocate( buf.capacity() ); + + // version tag [0] + inner.put( ( byte ) ( 0x00 | 0xa0 ) ); + inner.put( ( byte ) 3 ); // length + + inner.put( ( byte ) ( 0x02 ) ); // INTEGER tag + inner.put( ( byte ) 1 ); // length + inner.put( ( byte ) VERSION ); // value + + if ( negoToken != null ) + { + int len = negoToken.length; + final byte[] negoTokenLengthBytes = encodeLength( len ); + len += 1 + negoTokenLengthBytes.length; + final byte[] negoTokenLength1Bytes = encodeLength( len ); + len += 1 + negoTokenLength1Bytes.length; + final byte[] negoTokenLength2Bytes = encodeLength( len ); + len += 1 + negoTokenLength2Bytes.length; + final byte[] negoTokenLength3Bytes = encodeLength( len ); + len += 1 + negoTokenLength3Bytes.length; + final byte[] negoTokenLength4Bytes = encodeLength( len ); + + inner.put( ( byte ) ( 0x01 | 0xa0 ) ); // negoData tag [1] + inner.put( negoTokenLength4Bytes ); // length + + inner.put( ( byte ) ( 0x30 ) ); // SEQUENCE tag + inner.put( negoTokenLength3Bytes ); // length + + inner.put( ( byte ) ( 0x30 ) ); // .. of SEQUENCE tag + inner.put( negoTokenLength2Bytes ); // length + + inner.put( ( byte ) ( 0x00 | 0xa0 ) ); // negoToken tag [0] + inner.put( negoTokenLength1Bytes ); // length + + inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag + inner.put( negoTokenLengthBytes ); // length + + inner.put( negoToken ); + } + + if ( authInfo != null ) + { + final byte[] authInfoEncodedLength = encodeLength( authInfo.length ); + + inner.put( ( byte ) ( 0x02 | 0xa0 ) ); // authInfo tag [2] + inner.put( encodeLength( 1 + authInfoEncodedLength.length + authInfo.length ) ); // length + + inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag + inner.put( authInfoEncodedLength ); + inner.put( authInfo ); + } + + if ( pubKeyAuth != null ) + { + final byte[] pubKeyAuthEncodedLength = encodeLength( pubKeyAuth.length ); + + inner.put( ( byte ) ( 0x03 | 0xa0 ) ); // pubKeyAuth tag [3] + inner.put( encodeLength( 1 + pubKeyAuthEncodedLength.length + pubKeyAuth.length ) ); // length + + inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag + inner.put( pubKeyAuthEncodedLength ); + inner.put( pubKeyAuth ); + } + + inner.flip(); + + // SEQUENCE tag + buf.put( ( byte ) ( 0x10 | 0x20 ) ); + buf.put( encodeLength( inner.limit() ) ); + buf.put( inner ); + } + + + public String debugDump() + { + final StringBuilder sb = new StringBuilder( "TsRequest\n" ); + sb.append( " negoToken:\n" ); + sb.append( " " ); + DebugUtil.dump( sb, negoToken ); + sb.append( "\n" ); + sb.append( " authInfo:\n" ); + sb.append( " " ); + DebugUtil.dump( sb, authInfo ); + sb.append( "\n" ); + sb.append( " pubKeyAuth:\n" ); + sb.append( " " ); + DebugUtil.dump( sb, pubKeyAuth ); + return sb.toString(); + } + + + @Override + public String toString() + { + return "TsRequest(negoToken=" + Arrays.toString( negoToken ) + ", authInfo=" + + Arrays.toString( authInfo ) + ", pubKeyAuth=" + Arrays.toString( pubKeyAuth ) + ")"; + } + } + + static void getByteAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) + throws MalformedChallengeException + { + final byte bufByte = buf.get(); + if ( bufByte != expectedValue ) + { + parseError( buf, errorMessage + expectMessage( expectedValue, bufByte ) ); + } + } + + private static String expectMessage( final int expectedValue, final int realValue ) + { + return "(expected " + String.format( "%02X", expectedValue ) + ", got " + String.format( "%02X", realValue ) + + ")"; + } + + static int parseLength( final ByteBuffer buf ) + { + byte bufByte = buf.get(); + if ( bufByte == 0x80 ) + { + return -1; // infinite + } + if ( ( bufByte & 0x80 ) == 0x80 ) + { + final int size = bufByte & 0x7f; + int length = 0; + for ( int i = 0; i < size; i++ ) + { + bufByte = buf.get(); + length = ( length << 8 ) + ( bufByte & 0xff ); + } + return length; + } + else + { + return bufByte; + } + } + + static void getLengthAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) + throws MalformedChallengeException + { + final int bufLength = parseLength( buf ); + if ( expectedValue != bufLength ) + { + parseError( buf, errorMessage + expectMessage( expectedValue, bufLength ) ); + } + } + + static int getAndAssertContentSpecificTag( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException + { + final byte bufByte = buf.get(); + if ( ( bufByte & 0xe0 ) != 0xa0 ) + { + parseError( buf, errorMessage + ": wrong content-specific tag " + String.format( "%02X", bufByte ) ); + } + final int tag = bufByte & 0x1f; + return tag; + } + + static void parseError( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException + { + throw new MalformedChallengeException( + "Error parsing TsRequest (position:" + buf.position() + "): " + errorMessage ); + } + + static byte[] encodeLength( final int length ) + { + if ( length < 128 ) + { + final byte[] encoded = new byte[1]; + encoded[0] = ( byte ) length; + return encoded; + } + + int size = 1; + + int val = length; + while ( ( val >>>= 8 ) != 0 ) + { + size++; + } + + final byte[] encoded = new byte[1 + size]; + encoded[0] = ( byte ) ( size | 0x80 ); + + int shift = ( size - 1 ) * 8; + for ( int i = 0; i < size; i++ ) + { + encoded[i + 1] = ( byte ) ( length >> shift ); + shift -= 8; + } + + return encoded; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java b/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java index 862ab357ff..2c8110e292 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java @@ -1,96 +1,96 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.impl.auth; - - -import java.nio.ByteBuffer; - - -/** - * Simple debugging utility class for CredSSP and NTLM implementations. - */ -class DebugUtil -{ - - public static String dump( final ByteBuffer buf ) - { - final ByteBuffer dup = buf.duplicate(); - final StringBuilder sb = new StringBuilder( dup.toString() ); - sb.append( ": " ); - while ( dup.position() < dup.limit() ) - { - sb.append( String.format( "%02X ", dup.get() ) ); - } - return sb.toString(); - } - - - public static void dump( final StringBuilder sb, final byte[] bytes ) - { - if ( bytes == null ) - { - sb.append( "null" ); - return; - } - for ( byte b : bytes ) - { - sb.append( String.format( "%02X ", b ) ); - } - } - - - public static String dump( final byte[] bytes ) - { - final StringBuilder sb = new StringBuilder(); - dump( sb, bytes ); - return sb.toString(); - } - - - public static byte[] fromHex( final String hex ) - { - int i = 0; - final byte[] bytes = new byte[200000]; - int h = 0; - while ( h < hex.length() ) - { - if ( hex.charAt( h ) == ' ' ) - { - h++; - } - final String str = hex.substring( h, h + 2 ); - bytes[i] = ( byte ) Integer.parseInt( str, 16 ); - i++; - h = h + 2; - } - final byte[] outbytes = new byte[i]; - System.arraycopy( bytes, 0, outbytes, 0, i ); - return outbytes; - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.auth; + + +import java.nio.ByteBuffer; + + +/** + * Simple debugging utility class for CredSSP and NTLM implementations. + */ +class DebugUtil +{ + + public static String dump( final ByteBuffer buf ) + { + final ByteBuffer dup = buf.duplicate(); + final StringBuilder sb = new StringBuilder( dup.toString() ); + sb.append( ": " ); + while ( dup.position() < dup.limit() ) + { + sb.append( String.format( "%02X ", dup.get() ) ); + } + return sb.toString(); + } + + + public static void dump( final StringBuilder sb, final byte[] bytes ) + { + if ( bytes == null ) + { + sb.append( "null" ); + return; + } + for ( final byte b : bytes ) + { + sb.append( String.format( "%02X ", b ) ); + } + } + + + public static String dump( final byte[] bytes ) + { + final StringBuilder sb = new StringBuilder(); + dump( sb, bytes ); + return sb.toString(); + } + + + public static byte[] fromHex( final String hex ) + { + int i = 0; + final byte[] bytes = new byte[200000]; + int h = 0; + while ( h < hex.length() ) + { + if ( hex.charAt( h ) == ' ' ) + { + h++; + } + final String str = hex.substring( h, h + 2 ); + bytes[i] = ( byte ) Integer.parseInt( str, 16 ); + i++; + h = h + 2; + } + final byte[] outbytes = new byte[i]; + System.arraycopy( bytes, 0, outbytes, 0, i ); + return outbytes; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 70cbe50d4c..a8d14723cc 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -821,7 +821,7 @@ public byte[] getSealingKey() private Cipher initCipher() throws NTLMEngineException { - Cipher cipher; + final Cipher cipher; try { cipher = Cipher.getInstance( "RC4" ); @@ -834,7 +834,7 @@ private Cipher initCipher() throws NTLMEngineException cipher.init( Cipher.DECRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); } } - catch ( Exception e ) + catch ( final Exception e ) { throw new NTLMEngineException( e.getMessage(), e ); } @@ -1779,7 +1779,7 @@ private byte[] addGssMicAvsToTargetInfo( final byte[] originalTargetInfo, writeUShort( newTargetInfo, MSV_AV_CHANNEL_BINDINGS, appendLength + 8 ); writeUShort( newTargetInfo, 16, appendLength + 10 ); - byte[] channelBindingsHash; + final byte[] channelBindingsHash; try { final byte[] certBytes = peerServerCertificate.getEncoded(); @@ -1795,11 +1795,11 @@ private byte[] addGssMicAvsToTargetInfo( final byte[] originalTargetInfo, final MessageDigest md5 = getMD5(); channelBindingsHash = md5.digest( channelBindingStruct ); } - catch ( CertificateEncodingException e ) + catch ( final CertificateEncodingException e ) { throw new NTLMEngineException( e.getMessage(), e ); } - catch ( NoSuchAlgorithmException e ) + catch ( final NoSuchAlgorithmException e ) { throw new NTLMEngineException( e.getMessage(), e ); } @@ -1841,7 +1841,7 @@ static int rotintlft(final int val, final int numbits) { static MessageDigest getMD5() { try { return MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException ex) { + } catch (final NoSuchAlgorithmException ex) { throw new RuntimeException("MD5 message digest doesn't seem to exist - fatal error: "+ex.getMessage(), ex); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 4806e387f1..68259f3c71 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -1216,7 +1216,7 @@ public void close() throws IOException { connectionEvictor.shutdown(); try { connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS); - } catch (InterruptedException interrupted) { + } catch (final InterruptedException interrupted) { Thread.currentThread().interrupt(); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java index cee6d965f3..dbc205e0a3 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java @@ -135,7 +135,7 @@ public void validate(final Cookie cookie, final CookieOrigin origin) @Override public List
formatCookies(final List cookies) { Args.notEmpty(cookies, "List of cookies"); - List cookieList; + final List cookieList; if (cookies.size() > 1) { // Create a mutable copy and sort the copy. cookieList = new ArrayList(cookies); diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java b/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java index 657f8df93d..d04b7cab31 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java @@ -316,7 +316,7 @@ public void testHTTPCLIENT_1316() throws Exception{ @Test public void testHTTPCLIENT_1097() { - String cns[]; + final String cns[]; final String alt[] = {}; final X509HostnameVerifier bhv = new BrowserCompatHostnameVerifier(); final X509HostnameVerifier shv = new StrictHostnameVerifier(); diff --git a/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java b/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java index 8af33b6225..3bd3a825bd 100644 --- a/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java +++ b/httpclient/src/test/java/org/apache/http/impl/auth/TestNTLMEngineImpl.java @@ -76,7 +76,7 @@ static byte[] toBytes(final String hex) { /* Test suite MD4 helper */ static void checkMD4(final String input, final String hexOutput) throws Exception { - NTLMEngineImpl.MD4 md4; + final NTLMEngineImpl.MD4 md4; md4 = new NTLMEngineImpl.MD4(); md4.update(input.getBytes(Consts.ASCII)); final byte[] answer = md4.getOutput(); diff --git a/httpclient/src/test/java/org/apache/http/localserver/EchoHandler.java b/httpclient/src/test/java/org/apache/http/localserver/EchoHandler.java index 380607e400..298e77b60e 100644 --- a/httpclient/src/test/java/org/apache/http/localserver/EchoHandler.java +++ b/httpclient/src/test/java/org/apache/http/localserver/EchoHandler.java @@ -89,7 +89,7 @@ public void handle(final HttpRequest request, // For some reason, just putting the incoming entity into // the response will not work. We have to buffer the message. - byte[] data; + final byte[] data; if (entity == null) { data = new byte [0]; } else { From c165c06a9794d86718c212f61a82ce79b23dc751 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 31 Jul 2017 18:02:37 -0700 Subject: [PATCH 137/204] Clean up: Order GID before AID. --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 37e2ada8db..1809207251 100644 --- a/pom.xml +++ b/pom.xml @@ -25,8 +25,8 @@ . --> - project org.apache.httpcomponents + project 8 ../project/pom.xml @@ -216,7 +216,6 @@ true - ${maven.compiler.source} http://docs.oracle.com/javase/6/docs/api/ http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/ From 7dfd236dc155e97c650c9da9b4b3f9234b3b2de9 Mon Sep 17 00:00:00 2001 From: Tomas Celaya Date: Mon, 31 Jul 2017 18:10:03 -0700 Subject: [PATCH 138/204] [HTTPCLIENT-1865] DefaultServiceUnavailableRetryStrategy does not respect HttpEntity#isRepeatable. --- RELEASE_NOTES.txt | 3 ++ .../ServiceUnavailableRetryExec.java | 3 +- .../TestServiceUnavailableRetryExec.java | 32 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 932e10624a..30bb4e6802 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -8,6 +8,9 @@ Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- +* [HTTPCLIENT-1865] DefaultServiceUnavailableRetryStrategy does not respect HttpEntity#isRepeatable. + Contributed by Tomas Celaya + * [HTTPCLIENT-1833] Fix Windows Negotiate-NTLM handling of proxies. Contributed by Roman Stoffel diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java index 8b0c6f4342..f2131df963 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ServiceUnavailableRetryExec.java @@ -85,7 +85,8 @@ public CloseableHttpResponse execute( final CloseableHttpResponse response = this.requestExecutor.execute( route, request, context, execAware); try { - if (this.retryStrategy.retryRequest(response, c, context)) { + if (this.retryStrategy.retryRequest(response, c, context) + && RequestEntityProxy.isRepeatable(request)) { response.close(); final long nextInterval = this.retryStrategy.getRetryInterval(); if (nextInterval > 0) { diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java index 8356b6fe8d..bd4f27b739 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestServiceUnavailableRetryExec.java @@ -26,12 +26,14 @@ */ package org.apache.http.impl.execchain; +import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.client.ServiceUnavailableRetryStrategy; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.conn.routing.HttpRoute; @@ -115,4 +117,34 @@ public void testStrategyRuntimeException() throws Exception { throw ex; } } + + @Test + public void testNonRepeatableEntityResponseReturnedImmediately() throws Exception { + final HttpRoute route = new HttpRoute(target); + + final HttpEntity entity = Mockito.mock(HttpEntity.class); + Mockito.when(entity.isRepeatable()).thenReturn(Boolean.FALSE); + + final HttpPut put = new HttpPut("/test"); + put.setEntity(entity); + + final HttpRequestWrapper request = HttpRequestWrapper.wrap(put); + final HttpClientContext context = HttpClientContext.create(); + final CloseableHttpResponse response = Mockito.mock(CloseableHttpResponse.class); + + Mockito.when(requestExecutor.execute( + Mockito.eq(route), + Mockito.any(), + Mockito.any(), + Mockito.any())).thenReturn(response); + + Mockito.when(retryStrategy.retryRequest( + Mockito.any(), + Mockito.anyInt(), + Mockito.any())).thenReturn(Boolean.TRUE, Boolean.FALSE); + + retryExec.execute(route, request, context, execAware); + + Mockito.verify(response, Mockito.times(0)).close(); + } } From 73ace14858a6e23cdbb06a52b84995610767edf9 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 1 Aug 2017 11:42:07 +0200 Subject: [PATCH 139/204] Fixed javadocs in ResponseContentEncoding --- .../apache/http/client/protocol/ResponseContentEncoding.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java index 476eb63205..a40d03bf72 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/ResponseContentEncoding.java @@ -94,8 +94,8 @@ public ResponseContentEncoding(final Lookup decoderRegistry) * Handles {@code gzip} and {@code deflate} compressed entities by using the following * decoders: *
    - *
  • gzip - see {@link GZIPInputStream}
  • - *
  • deflate - see {@link DeflateInputStream}
  • + *
  • gzip - see {@link java.util.zip.GZIPInputStream}
  • + *
  • deflate - see {@link org.apache.http.client.entity.DeflateInputStream}
  • *
*/ public ResponseContentEncoding() { From dd4da037c717e436fac35b98942079a269cb4765 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Mon, 7 Aug 2017 09:47:04 -0400 Subject: [PATCH 140/204] BasicCookieStore no longer synchronizes on reads BasicCookieStore uses a ReentrantReadWriteLock to avoid synchronization on getCookies/toString while maintaining thread safety. --- .../http/impl/client/BasicCookieStore.java | 73 +++++++++++++------ 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java index d2468f6330..c536c6e18f 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java @@ -32,6 +32,8 @@ import java.util.Iterator; import java.util.List; import java.util.TreeSet; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.http.annotation.Contract; import org.apache.http.annotation.ThreadingBehavior; @@ -51,10 +53,12 @@ public class BasicCookieStore implements CookieStore, Serializable { private static final long serialVersionUID = -7581093305228232025L; private final TreeSet cookies; + private final ReadWriteLock lock; public BasicCookieStore() { super(); this.cookies = new TreeSet(new CookieIdentityComparator()); + this.lock = new ReentrantReadWriteLock(); } /** @@ -68,12 +72,17 @@ public BasicCookieStore() { * */ @Override - public synchronized void addCookie(final Cookie cookie) { + public void addCookie(final Cookie cookie) { if (cookie != null) { - // first remove any old cookie that is equivalent - cookies.remove(cookie); - if (!cookie.isExpired(new Date())) { - cookies.add(cookie); + lock.writeLock().lock(); + try { + // first remove any old cookie that is equivalent + cookies.remove(cookie); + if (!cookie.isExpired(new Date())) { + cookies.add(cookie); + } + } finally { + lock.writeLock().unlock(); } } } @@ -88,10 +97,10 @@ public synchronized void addCookie(final Cookie cookie) { * @see #addCookie(Cookie) * */ - public synchronized void addCookies(final Cookie[] cookies) { + public void addCookies(final Cookie[] cookies) { if (cookies != null) { - for (final Cookie cooky : cookies) { - this.addCookie(cooky); + for (final Cookie cookie : cookies) { + this.addCookie(cookie); } } } @@ -103,9 +112,14 @@ public synchronized void addCookies(final Cookie[] cookies) { * @return an array of {@link Cookie cookies}. */ @Override - public synchronized List getCookies() { - //create defensive copy so it won't be concurrently modified - return new ArrayList(cookies); + public List getCookies() { + lock.readLock().lock(); + try { + //create defensive copy so it won't be concurrently modified + return new ArrayList(cookies); + } finally { + lock.readLock().unlock(); + } } /** @@ -117,31 +131,46 @@ public synchronized List getCookies() { * @see Cookie#isExpired(Date) */ @Override - public synchronized boolean clearExpired(final Date date) { + public boolean clearExpired(final Date date) { if (date == null) { return false; } - boolean removed = false; - for (final Iterator it = cookies.iterator(); it.hasNext();) { - if (it.next().isExpired(date)) { - it.remove(); - removed = true; + lock.writeLock().lock(); + try { + boolean removed = false; + for (final Iterator it = cookies.iterator(); it.hasNext(); ) { + if (it.next().isExpired(date)) { + it.remove(); + removed = true; + } } + return removed; + } finally { + lock.writeLock().unlock(); } - return removed; } /** * Clears all cookies. */ @Override - public synchronized void clear() { - cookies.clear(); + public void clear() { + lock.writeLock().lock(); + try { + cookies.clear(); + } finally { + lock.writeLock().unlock(); + } } @Override - public synchronized String toString() { - return cookies.toString(); + public String toString() { + lock.readLock().lock(); + try { + return cookies.toString(); + } finally { + lock.readLock().unlock(); + } } } From 5f9a6c01d866edb75b5063cb3e748990a5bd5252 Mon Sep 17 00:00:00 2001 From: Andy Klimczak Date: Wed, 6 Sep 2017 14:56:25 -0600 Subject: [PATCH 141/204] Fix typo in HttpClients.java Javadoc closes #83. --- .../src/main/java/org/apache/http/impl/client/HttpClients.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java index c43b460ac5..5e10aa0cf1 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClients.java @@ -58,7 +58,7 @@ public static CloseableHttpClient createDefault() { /** * Creates {@link CloseableHttpClient} instance with default - * configuration based on ssytem properties. + * configuration based on system properties. */ public static CloseableHttpClient createSystem() { return HttpClientBuilder.create().useSystemProperties().build(); From f272674277ccc5a07056f9d5fd94d12363196c2f Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 14 Sep 2017 13:27:00 +0200 Subject: [PATCH 142/204] Upgraded HttpCore dependency to version 4.4.7 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1809207251..9106b1d5b9 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 1.6 1.6 - 4.4.6 + 4.4.7 1.2 1.10 2.6.11 From 84a5fba63df8095882945ada3f9ea608e78690b7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 24 Sep 2017 12:34:46 -0600 Subject: [PATCH 143/204] Update httpcomponents-parent from 8 to 9. --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 9106b1d5b9..fde1efe0bc 100644 --- a/pom.xml +++ b/pom.xml @@ -26,9 +26,9 @@ --> org.apache.httpcomponents - project - 8 - ../project/pom.xml + httpcomponents-parent + 9 + ../httpcomponents-parent/pom.xml 4.0.0 httpcomponents-client From 74514b65ffbe7841763e95242fd8d867676d5832 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 29 Sep 2017 11:16:44 +0200 Subject: [PATCH 144/204] Travis-CI configuration --- .travis.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..9b6c70beaf --- /dev/null +++ b/.travis.yml @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +language: java +sudo: false + +jdk: + - openjdk7 + +after_success: + - mvn clean cobertura:cobertura coveralls:report From 7e44b9635e5de8ffce100f4ce4fc3e5d0dedb63b Mon Sep 17 00:00:00 2001 From: "alessandro.gherardi" Date: Mon, 2 Oct 2017 10:06:07 -0600 Subject: [PATCH 145/204] HTTPCLIENT-1855: Update DIGEST nonce counter in auth cache after auth challenge --- .../client/protocol/RequestAuthCache.java | 4 ++- .../client/protocol/TestRequestAuthCache.java | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java index aa30073563..7bf37e6b8c 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java @@ -44,6 +44,7 @@ import org.apache.http.auth.Credentials; import org.apache.http.client.AuthCache; import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.AuthSchemes; import org.apache.http.conn.routing.RouteInfo; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; @@ -135,7 +136,8 @@ private void doPreemptiveAuth( final Credentials creds = credsProvider.getCredentials(authScope); if (creds != null) { - if ("BASIC".equalsIgnoreCase(authScheme.getSchemeName())) { + if (AuthSchemes.BASIC.equalsIgnoreCase(authScheme.getSchemeName()) + || AuthSchemes.DIGEST.equalsIgnoreCase(authScheme.getSchemeName())) { authState.setState(AuthProtocolState.CHALLENGED); } else { authState.setState(AuthProtocolState.SUCCESS); diff --git a/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java b/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java index 6bc3d95b91..1c0d323996 100644 --- a/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java +++ b/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java @@ -37,6 +37,7 @@ import org.apache.http.client.AuthCache; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.auth.DigestScheme; import org.apache.http.impl.client.BasicAuthCache; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.message.BasicHttpRequest; @@ -55,6 +56,8 @@ public class TestRequestAuthCache { private AuthScope authscope2; private BasicScheme authscheme1; private BasicScheme authscheme2; + private DigestScheme digestAuthscheme1; + private DigestScheme digestAuthscheme2; private BasicCredentialsProvider credProvider; private AuthState targetState; private AuthState proxyState; @@ -71,6 +74,8 @@ public void setUp() { this.authscope2 = new AuthScope(this.proxy); this.authscheme1 = new BasicScheme(); this.authscheme2 = new BasicScheme(); + this.digestAuthscheme1 = new DigestScheme(); + this.digestAuthscheme2 = new DigestScheme(); this.credProvider.setCredentials(this.authscope1, this.creds1); this.credProvider.setCredentials(this.authscope2, this.creds2); @@ -118,6 +123,33 @@ public void testPreemptiveTargetAndProxyAuth() throws Exception { Assert.assertSame(this.creds2, this.proxyState.getCredentials()); } + @Test + public void testPreemptiveTargetAndProxyAuthDigest() throws Exception { + final HttpRequest request = new BasicHttpRequest("GET", "/"); + + final HttpClientContext context = HttpClientContext.create(); + context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credProvider); + context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, this.target); + context.setAttribute(HttpClientContext.HTTP_ROUTE, new HttpRoute(this.target, null, this.proxy, false)); + context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, this.targetState); + context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, this.proxyState); + + final AuthCache authCache = new BasicAuthCache(); + authCache.put(this.target, this.digestAuthscheme1); + authCache.put(this.proxy, this.digestAuthscheme2); + + context.setAttribute(HttpClientContext.AUTH_CACHE, authCache); + + final HttpRequestInterceptor interceptor = new RequestAuthCache(); + interceptor.process(request, context); + Assert.assertNotNull(this.targetState.getAuthScheme()); + Assert.assertSame(this.targetState.getState(), AuthProtocolState.CHALLENGED); + Assert.assertSame(this.creds1, this.targetState.getCredentials()); + Assert.assertNotNull(this.proxyState.getAuthScheme()); + Assert.assertSame(this.proxyState.getState(), AuthProtocolState.CHALLENGED); + Assert.assertSame(this.creds2, this.proxyState.getCredentials()); + } + @Test public void testCredentialsProviderNotSet() throws Exception { final HttpRequest request = new BasicHttpRequest("GET", "/"); From aa0e53cc0c63d581c8e0e5b151ec987a8b3a4a73 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 4 Oct 2017 11:54:52 +0200 Subject: [PATCH 146/204] Removed explicit plugin version declaration (should be inherited from the parent POM) --- fluent-hc/pom.xml | 3 --- httpclient-cache/pom.xml | 3 --- httpclient-osgi/pom.xml | 1 - httpclient-win/pom.xml | 3 --- httpclient/pom.xml | 3 --- httpmime/pom.xml | 3 --- pom.xml | 3 --- 7 files changed, 19 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 99fea1a319..1f2f217a32 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -110,7 +110,6 @@ maven-project-info-reports-plugin - ${hc.project-info.version} false @@ -125,12 +124,10 @@ maven-jxr-plugin - ${hc.jxr.version} maven-surefire-report-plugin - ${hc.surefire-report.version} diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index eda4286548..1f4ffad26e 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -169,7 +169,6 @@ maven-project-info-reports-plugin - ${hc.project-info.version} false @@ -184,12 +183,10 @@ maven-jxr-plugin - ${hc.jxr.version} maven-surefire-report-plugin - ${hc.surefire-report.version} diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 7ac38ceac2..78f97ec9a7 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -190,7 +190,6 @@ maven-project-info-reports-plugin - ${hc.project-info.version} false diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index be33e8079f..a87ac878e6 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -95,7 +95,6 @@ maven-project-info-reports-plugin - ${hc.project-info.version} false @@ -110,12 +109,10 @@ maven-jxr-plugin - ${hc.jxr.version} maven-surefire-report-plugin - ${hc.surefire-report.version} diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 2977db2892..3a6b0c843f 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -154,7 +154,6 @@ maven-project-info-reports-plugin - ${hc.project-info.version} false @@ -169,12 +168,10 @@ maven-jxr-plugin - ${hc.jxr.version} maven-surefire-report-plugin - ${hc.surefire-report.version} diff --git a/httpmime/pom.xml b/httpmime/pom.xml index ffe027490a..8130d92559 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -118,7 +118,6 @@ maven-project-info-reports-plugin - ${hc.project-info.version} false @@ -133,12 +132,10 @@ maven-jxr-plugin - ${hc.jxr.version} maven-surefire-report-plugin - ${hc.surefire-report.version} diff --git a/pom.xml b/pom.xml index fde1efe0bc..29f8091b3c 100644 --- a/pom.xml +++ b/pom.xml @@ -360,7 +360,6 @@ org.codehaus.mojo clirr-maven-plugin - ${hc.clirr.version} ${api.comparison.version} @@ -392,7 +391,6 @@ maven-project-info-reports-plugin - ${hc.project-info.version} false @@ -410,7 +408,6 @@ org.codehaus.mojo clirr-maven-plugin - ${hc.clirr.version} ${api.comparison.version} From ad606e45bf4dabf6d347db3ced83a88f9f3b407b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 4 Oct 2017 15:00:20 -0600 Subject: [PATCH 147/204] Javadoc. --- .../http/client/entity/EntityBuilder.java | 111 ++++++++++-------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java b/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java index 3c966785c7..34a2c4edc1 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/EntityBuilder.java @@ -100,13 +100,15 @@ public String getText() { } /** - * Sets entity content as a string. This method is mutually exclusive with - * {@link #setBinary(byte[])}, - * {@link #setStream(java.io.InputStream)} , - * {@link #setSerializable(java.io.Serializable)} , - * {@link #setParameters(java.util.List)}, - * {@link #setParameters(org.apache.http.NameValuePair...)} - * {@link #setFile(java.io.File)} methods. + * Sets entity content as a string. This method is mutually exclusive with: + *
    + *
  • {@link #setBinary(byte[])}
  • + *
  • {@link #setStream(java.io.InputStream)}
  • + *
  • {@link #setSerializable(java.io.Serializable)}
  • + *
  • {@link #setParameters(java.util.List)}
  • + *
  • {@link #setParameters(org.apache.http.NameValuePair...)}
  • + *
  • {@link #setFile(java.io.File)}
  • + *
      */ public EntityBuilder setText(final String text) { clearContent(); @@ -123,13 +125,16 @@ public byte[] getBinary() { } /** - * Sets entity content as a byte array. This method is mutually exclusive with - * {@link #setText(String)}, - * {@link #setStream(java.io.InputStream)} , - * {@link #setSerializable(java.io.Serializable)} , - * {@link #setParameters(java.util.List)}, - * {@link #setParameters(org.apache.http.NameValuePair...)} - * {@link #setFile(java.io.File)} methods. + * Sets entity content as a byte array. This method is mutually exclusive + * with: + *
        + *
      • {@link #setText(String)}
      • + *
      • {@link #setStream(java.io.InputStream)}
      • + *
      • {@link #setSerializable(java.io.Serializable)}
      • + *
      • {@link #setParameters(java.util.List)}
      • + *
      • {@link #setParameters(org.apache.http.NameValuePair...)}
      • + *
      • {@link #setFile(java.io.File)}
      • + *
      */ public EntityBuilder setBinary(final byte[] binary) { clearContent(); @@ -146,13 +151,16 @@ public InputStream getStream() { } /** - * Sets entity content as a {@link InputStream}. This method is mutually exclusive with - * {@link #setText(String)}, - * {@link #setBinary(byte[])}, - * {@link #setSerializable(java.io.Serializable)} , - * {@link #setParameters(java.util.List)}, - * {@link #setParameters(org.apache.http.NameValuePair...)} - * {@link #setFile(java.io.File)} methods. + * Sets entity content as a {@link InputStream}. This method is mutually + * exclusive with: + *
        + *
      • {@link #setText(String)}
      • + *
      • {@link #setBinary(byte[])}
      • + *
      • {@link #setSerializable(java.io.Serializable)}
      • + *
      • {@link #setParameters(java.util.List)}
      • + *
      • {@link #setParameters(org.apache.http.NameValuePair...)}
      • + *
      • {@link #setFile(java.io.File)}
      • + *
      */ public EntityBuilder setStream(final InputStream stream) { clearContent(); @@ -170,12 +178,15 @@ public List getParameters() { } /** - * Sets entity content as a parameter list. This method is mutually exclusive with - * {@link #setText(String)}, - * {@link #setBinary(byte[])}, - * {@link #setStream(java.io.InputStream)} , - * {@link #setSerializable(java.io.Serializable)} , - * {@link #setFile(java.io.File)} methods. + * Sets entity content as a parameter list. This method is mutually + * exclusive with: + *
        + *
      • {@link #setText(String)}
      • + *
      • {@link #setBinary(byte[])}
      • + *
      • {@link #setStream(java.io.InputStream)}
      • + *
      • {@link #setSerializable(java.io.Serializable)}
      • + *
      • {@link #setFile(java.io.File)}
      • + *
      */ public EntityBuilder setParameters(final List parameters) { clearContent(); @@ -184,12 +195,14 @@ public EntityBuilder setParameters(final List parameters) { } /** - * Sets entity content as a parameter list. This method is mutually exclusive with - * {@link #setText(String)}, - * {@link #setBinary(byte[])}, - * {@link #setStream(java.io.InputStream)} , - * {@link #setSerializable(java.io.Serializable)} , - * {@link #setFile(java.io.File)} methods. + * Sets entity content as a parameter list. This method is mutually exclusive with: + *
        + *
      • {@link #setText(String)}
      • + *
      • {@link #setBinary(byte[])}
      • + *
      • {@link #setStream(java.io.InputStream)}
      • + *
      • {@link #setSerializable(java.io.Serializable)}
      • + *
      • {@link #setFile(java.io.File)}
      • + *
      */ public EntityBuilder setParameters(final NameValuePair... parameters) { return setParameters(Arrays.asList(parameters)); @@ -204,13 +217,15 @@ public Serializable getSerializable() { } /** - * Sets entity content as a {@link Serializable}. This method is mutually exclusive with - * {@link #setText(String)}, - * {@link #setBinary(byte[])}, - * {@link #setStream(java.io.InputStream)} , - * {@link #setParameters(java.util.List)}, - * {@link #setParameters(org.apache.http.NameValuePair...)} - * {@link #setFile(java.io.File)} methods. + * Sets entity content as a {@link Serializable}. This method is mutually exclusive with: + *
        + *
      • {@link #setText(String)}
      • + *
      • {@link #setBinary(byte[])}
      • + *
      • {@link #setStream(java.io.InputStream)}
      • + *
      • {@link #setParameters(java.util.List)}
      • + *
      • {@link #setParameters(org.apache.http.NameValuePair...)}
      • + *
      • {@link #setFile(java.io.File)}
      • + *
      */ public EntityBuilder setSerializable(final Serializable serializable) { clearContent(); @@ -227,13 +242,15 @@ public File getFile() { } /** - * Sets entity content as a {@link File}. This method is mutually exclusive with - * {@link #setText(String)}, - * {@link #setBinary(byte[])}, - * {@link #setStream(java.io.InputStream)} , - * {@link #setParameters(java.util.List)}, - * {@link #setParameters(org.apache.http.NameValuePair...)} - * {@link #setSerializable(java.io.Serializable)} methods. + * Sets entity content as a {@link File}. This method is mutually exclusive with: + *
        + *
      • {@link #setText(String)}
      • + *
      • {@link #setBinary(byte[])}
      • + *
      • {@link #setStream(java.io.InputStream)}
      • + *
      • {@link #setParameters(java.util.List)}
      • + *
      • {@link #setParameters(org.apache.http.NameValuePair...)}
      • + *
      • {@link #setSerializable(java.io.Serializable)}
      • + *
          */ public EntityBuilder setFile(final File file) { clearContent(); From cfbbea0ee3ee90590106aa906eec5e9864b9a24c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 15 Oct 2017 13:29:59 +0200 Subject: [PATCH 148/204] Fixed NPE in case of a missing Max-Forwards header --- .../org/apache/http/impl/client/cache/CachingHttpClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java index 20f54cf629..a564dc11bc 100644 --- a/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java +++ b/httpclient-cache/src/main/java-deprecated/org/apache/http/impl/client/cache/CachingHttpClient.java @@ -748,7 +748,8 @@ boolean clientRequestsOurOptions(final HttpRequest request) { return false; } - if (!"0".equals(request.getFirstHeader(HeaderConstants.MAX_FORWARDS).getValue())) { + final Header h = request.getFirstHeader(HeaderConstants.MAX_FORWARDS); + if (!"0".equals(h != null ? h.getValue() : null)) { return false; } From aa81865776f4d664b829981071fbd9fd83203d6f Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 19 Oct 2017 20:07:49 +0200 Subject: [PATCH 149/204] HTTPCLIENT-1855: Removed code causing unnecessary auth cache updated; Reverted 7e44b96 --- .../client/protocol/RequestAuthCache.java | 7 ----- .../client/protocol/TestRequestAuthCache.java | 27 ------------------- 2 files changed, 34 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java index 7bf37e6b8c..ab68515815 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java @@ -44,7 +44,6 @@ import org.apache.http.auth.Credentials; import org.apache.http.client.AuthCache; import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.AuthSchemes; import org.apache.http.conn.routing.RouteInfo; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; @@ -136,12 +135,6 @@ private void doPreemptiveAuth( final Credentials creds = credsProvider.getCredentials(authScope); if (creds != null) { - if (AuthSchemes.BASIC.equalsIgnoreCase(authScheme.getSchemeName()) - || AuthSchemes.DIGEST.equalsIgnoreCase(authScheme.getSchemeName())) { - authState.setState(AuthProtocolState.CHALLENGED); - } else { - authState.setState(AuthProtocolState.SUCCESS); - } authState.update(authScheme, creds); } else { this.log.debug("No credentials for preemptive authentication"); diff --git a/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java b/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java index 1c0d323996..3f0d8e9582 100644 --- a/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java +++ b/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAuthCache.java @@ -123,33 +123,6 @@ public void testPreemptiveTargetAndProxyAuth() throws Exception { Assert.assertSame(this.creds2, this.proxyState.getCredentials()); } - @Test - public void testPreemptiveTargetAndProxyAuthDigest() throws Exception { - final HttpRequest request = new BasicHttpRequest("GET", "/"); - - final HttpClientContext context = HttpClientContext.create(); - context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credProvider); - context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, this.target); - context.setAttribute(HttpClientContext.HTTP_ROUTE, new HttpRoute(this.target, null, this.proxy, false)); - context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, this.targetState); - context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, this.proxyState); - - final AuthCache authCache = new BasicAuthCache(); - authCache.put(this.target, this.digestAuthscheme1); - authCache.put(this.proxy, this.digestAuthscheme2); - - context.setAttribute(HttpClientContext.AUTH_CACHE, authCache); - - final HttpRequestInterceptor interceptor = new RequestAuthCache(); - interceptor.process(request, context); - Assert.assertNotNull(this.targetState.getAuthScheme()); - Assert.assertSame(this.targetState.getState(), AuthProtocolState.CHALLENGED); - Assert.assertSame(this.creds1, this.targetState.getCredentials()); - Assert.assertNotNull(this.proxyState.getAuthScheme()); - Assert.assertSame(this.proxyState.getState(), AuthProtocolState.CHALLENGED); - Assert.assertSame(this.creds2, this.proxyState.getCredentials()); - } - @Test public void testCredentialsProviderNotSet() throws Exception { final HttpRequest request = new BasicHttpRequest("GET", "/"); From 1383e1f781012e767c0cc811aeef77e28264682d Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 20 Oct 2017 11:45:12 +0200 Subject: [PATCH 150/204] HTTPCLIENT-1855: disabled caching of DIGEST auth scheme instances due to unreliability of nonce counter when the auth cache is shared by multiple sessions --- .../apache/http/impl/client/AuthenticationStrategyAdaptor.java | 3 +-- .../apache/http/impl/client/AuthenticationStrategyImpl.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java index f72ae07f62..d09b6700f0 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java @@ -167,8 +167,7 @@ private boolean isCachable(final AuthScheme authScheme) { return false; } final String schemeName = authScheme.getSchemeName(); - return schemeName.equalsIgnoreCase(AuthPolicy.BASIC) || - schemeName.equalsIgnoreCase(AuthPolicy.DIGEST); + return schemeName.equalsIgnoreCase(AuthPolicy.BASIC); } public AuthenticationHandler getHandler() { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java index 1f35e61c56..4ca17c37f0 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java @@ -237,8 +237,7 @@ protected boolean isCachable(final AuthScheme authScheme) { return false; } final String schemeName = authScheme.getSchemeName(); - return schemeName.equalsIgnoreCase(AuthSchemes.BASIC) || - schemeName.equalsIgnoreCase(AuthSchemes.DIGEST); + return schemeName.equalsIgnoreCase(AuthSchemes.BASIC); } @Override From 2e303b854f88b67d98820bdd9cfdeac01f0ee54e Mon Sep 17 00:00:00 2001 From: aleh_struneuski Date: Wed, 25 Oct 2017 11:02:42 +0300 Subject: [PATCH 151/204] HTTPCLIENT-1876. Improve the buildString() method in URIBuilder. --- .../apache/http/client/utils/URIBuilder.java | 2 +- .../http/client/utils/TestURIBuilder.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java index 91f198c3e2..0a79b4a1ea 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java @@ -152,7 +152,7 @@ private String buildString() { } if (this.encodedQuery != null) { sb.append("?").append(this.encodedQuery); - } else if (this.queryParams != null) { + } else if (this.queryParams != null && !this.queryParams.isEmpty()) { sb.append("?").append(encodeUrlForm(this.queryParams)); } else if (this.query != null) { sb.append("?").append(encodeUric(this.query)); diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java index 8bca89ef11..f96178b0ae 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURIBuilder.java @@ -30,6 +30,7 @@ import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.apache.http.Consts; @@ -130,6 +131,22 @@ public void testSetParameter() throws Exception { Assert.assertEquals(new URI("http://localhost:80/?param=some+other+stuff&blah=blah"), result); } + @Test + public void testSetParametersWithEmptyArg() throws Exception { + final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null); + final URIBuilder uribuilder = new URIBuilder(uri).setParameters(); + final URI result = uribuilder.build(); + Assert.assertEquals(new URI("http://localhost:80/test"), result); + } + + @Test + public void testSetParametersWithEmptyList() throws Exception { + final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null); + final URIBuilder uribuilder = new URIBuilder(uri).setParameters(Arrays.asList()); + final URI result = uribuilder.build(); + Assert.assertEquals(new URI("http://localhost:80/test"), result); + } + @Test public void testParameterWithSpecialChar() throws Exception { final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff", null); From d6db9ab3d079b44e0a524dacf5e7ce9463618950 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 16 Nov 2017 20:17:16 +0100 Subject: [PATCH 152/204] HTTPCLIENT-1879: re-apply SocketConfig#socketTimeout to connections leased by the pooling and basic connection managers --- .../BasicHttpClientConnectionManager.java | 2 ++ .../PoolingHttpClientConnectionManager.java | 36 +++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java index 08153cdd12..5f694436d2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java @@ -258,6 +258,7 @@ synchronized HttpClientConnection getConnection(final HttpRoute route, final Obj if (this.conn == null) { this.conn = this.connFactory.create(route, this.connConfig); } + this.conn.setSocketTimeout(this.socketConfig.getSoTimeout()); this.leased = true; return this.conn; } @@ -284,6 +285,7 @@ public synchronized void releaseConnection( this.expiry = Long.MAX_VALUE; } else { this.state = state; + this.conn.setSocketTimeout(0); if (this.log.isDebugEnabled()) { final String s; if (keepalive > 0) { diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java index 81928acb56..b20e0248e4 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java @@ -28,7 +28,6 @@ import java.io.Closeable; import java.io.IOException; -import java.net.InetSocketAddress; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -246,6 +245,17 @@ private String format(final CPoolEntry entry) { return buf.toString(); } + private SocketConfig resolveSocketConfig(final HttpHost host) { + SocketConfig socketConfig = this.configData.getSocketConfig(host); + if (socketConfig == null) { + socketConfig = this.configData.getDefaultSocketConfig(); + } + if (socketConfig == null) { + socketConfig = SocketConfig.DEFAULT; + } + return socketConfig; + } + @Override public ConnectionRequest requestConnection( final HttpRoute route, @@ -266,7 +276,18 @@ public boolean cancel() { public HttpClientConnection get( final long timeout, final TimeUnit tunit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException { - return leaseConnection(future, timeout, tunit); + final HttpClientConnection conn = leaseConnection(future, timeout, tunit); + if (conn.isOpen()) { + final HttpHost host; + if (route.getProxyHost() != null) { + host = route.getProxyHost(); + } else { + host = route.getTargetHost(); + } + final SocketConfig socketConfig = resolveSocketConfig(host); + conn.setSocketTimeout(socketConfig.getSoTimeout()); + } + return conn; } }; @@ -319,6 +340,7 @@ public void releaseConnection( } this.log.debug("Connection " + format(entry) + " can be kept alive " + s); } + conn.setSocketTimeout(0); } } finally { this.pool.release(entry, conn.isOpen() && entry.isRouteComplete()); @@ -348,16 +370,8 @@ public void connect( } else { host = route.getTargetHost(); } - final InetSocketAddress localAddress = route.getLocalSocketAddress(); - SocketConfig socketConfig = this.configData.getSocketConfig(host); - if (socketConfig == null) { - socketConfig = this.configData.getDefaultSocketConfig(); - } - if (socketConfig == null) { - socketConfig = SocketConfig.DEFAULT; - } this.connectionOperator.connect( - conn, host, localAddress, connectTimeout, socketConfig, context); + conn, host, route.getLocalSocketAddress(), connectTimeout, resolveSocketConfig(host), context); } @Override From 97eee9e0e0adcb917db20550225db717238f6982 Mon Sep 17 00:00:00 2001 From: Karl Wright Date: Sat, 18 Nov 2017 06:54:59 -0500 Subject: [PATCH 153/204] HTTPCLIENT-1881: Allow truncated NTLM packets to work with this client. --- .../java/org/apache/http/impl/auth/NTLMEngineImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index a8d14723cc..6ed5c0ecfa 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -211,7 +211,7 @@ static String getType3Message(final String user, final String password, final St private static int readULong(final byte[] src, final int index) throws NTLMEngineException { if (src.length < index + 4) { - throw new NTLMEngineException("NTLM authentication - buffer too small for DWORD"); + return 0; } return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); @@ -219,7 +219,7 @@ private static int readULong(final byte[] src, final int index) throws NTLMEngin private static int readUShort(final byte[] src, final int index) throws NTLMEngineException { if (src.length < index + 2) { - throw new NTLMEngineException("NTLM authentication - buffer too small for WORD"); + return 0; } return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); } @@ -228,8 +228,7 @@ private static byte[] readSecurityBuffer(final byte[] src, final int index) thro final int length = readUShort(src, index); final int offset = readULong(src, index + 4); if (src.length < offset + length) { - throw new NTLMEngineException( - "NTLM authentication - buffer too small for data item"); + return new byte[length]; } final byte[] buffer = new byte[length]; System.arraycopy(src, offset, buffer, 0, length); From 0a7ca044cc18acb21829099bc2a5d159a802546a Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 25 Nov 2017 11:01:50 +0100 Subject: [PATCH 154/204] Updated repository details in DOAP; removed outdated release data --- doap_HttpComponents_Client.rdf | 129 +-------------------------------- 1 file changed, 4 insertions(+), 125 deletions(-) diff --git a/doap_HttpComponents_Client.rdf b/doap_HttpComponents_Client.rdf index dd17002c36..4f58195c91 100644 --- a/doap_HttpComponents_Client.rdf +++ b/doap_HttpComponents_Client.rdf @@ -53,132 +53,11 @@ This is the successor to the widely used Jakarta Commons HttpClient 3.1. - - - - httpcomponents-client-4.0-alpha1 - 2007-07-20 - 4.0-alpha1 - - - - - httpcomponents-client-4.0-alpha2 - 2007-11-07 - 4.0-alpha2 - - - - - httpcomponents-client-4.0-alpha3 - 2008-02-26 - 4.0-alpha3 - - - - - httpcomponents-client-4.0-alpha4 - 2008-05-09 - 4.0-alpha4 - - - - - httpcomponents-client-4.0-beta1 - 2008-08-29 - 4.0-beta1 - - - - - httpcomponents-client-4.0-beta2 - 2008-12-20 - 4.0-beta2 - - - - - httpcomponents-client-4.0 - 2009-08-14 - 4.0 - - - - - httpcomponents-client-4.0.1 - 2009-12-11 - 4.0.1 - - - - - httpcomponents-client-4.1-alpha1 - 2009-12-11 - 4.1-alpha1 - - - - - httpcomponents-client-4.1-alpha2 - 2010-05-19 - 4.1-alpha2 - - - - - httpcomponents-client-4.0.2 - 2010-09-09 - 4.0.2 - - - - - httpcomponents-client-4.0.3 - 2010-09-19 - 4.0.3 - - - - - httpcomponents-client-4.1-beta1 - 2010-11-21 - 4.1-beta1 - - - - - httpcomponents-client-4.1 GA - 2011-01-24 - 4.1 GA - - - - - httpcomponents-client-4.1.1 GA - 2011-03-20 - 4.1.1 GA - - - - - httpcomponents-client-4.1.2 GA - 2011-08-07 - 4.1.2 GA - - - - - httpcomponents-client-4.2-alpha1 - 2011-11-03 - 4.2-alpha1 - - - - - - - + + + + From 73f99953f3727f20338571f04d9ee5faec32c9d0 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 25 Nov 2017 11:04:23 +0100 Subject: [PATCH 155/204] Upgraded HttpComponents Parent to version 10 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 29f8091b3c..2951041a58 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.httpcomponents httpcomponents-parent - 9 + 10 ../httpcomponents-parent/pom.xml 4.0.0 From 6da7ec26091d7a77ef172d922de567a046ecd92b Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 25 Nov 2017 11:32:21 +0100 Subject: [PATCH 156/204] Changed test case failing in TravisCI due to what might be a local host name resolution problem --- .../apache/http/impl/client/integration/TestRedirects.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestRedirects.java b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestRedirects.java index ffa0ec48ab..b6ade302de 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestRedirects.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestRedirects.java @@ -87,16 +87,12 @@ public void handle( final HttpResponse response, final HttpContext context) throws HttpException, IOException { final HttpInetConnection conn = (HttpInetConnection) context.getAttribute(HttpCoreContext.HTTP_CONNECTION); - String localhost = conn.getLocalAddress().getHostName(); - if (localhost.equals("127.0.0.1")) { - localhost = "localhost"; - } final int port = conn.getLocalPort(); final String uri = request.getRequestLine().getUri(); if (uri.equals("/oldlocation/")) { response.setStatusCode(this.statuscode); response.addHeader(new BasicHeader("Location", - "http://" + localhost + ":" + port + "/newlocation/")); + "http://localhost:" + port + "/newlocation/")); response.addHeader(new BasicHeader("Connection", "close")); } else if (uri.equals("/newlocation/")) { response.setStatusCode(HttpStatus.SC_OK); From e249943247833df990c339e17b12209c1d2f4cdb Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 26 Nov 2017 16:03:06 +0100 Subject: [PATCH 157/204] HTTPCLIENT-1883: Added https.proxy* to the list of system properties taken into account by HttpClientBuilder --- .../org/apache/http/impl/client/SystemDefaultHttpClient.java | 2 ++ .../java/org/apache/http/impl/client/HttpClientBuilder.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java index b8cecf22ce..3eb6212618 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/SystemDefaultHttpClient.java @@ -59,6 +59,8 @@ *
        • javax.net.ssl.keyStorePassword
        • *
        • http.proxyHost
        • *
        • http.proxyPort
        • + *
        • https.proxyHost
        • + *
        • https.proxyPort
        • *
        • http.nonProxyHosts
        • *
        • http.keepAlive
        • *
        • http.maxConnections
        • diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java index 68259f3c71..3a7c5613b9 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java @@ -139,6 +139,8 @@ *
        • https.cipherSuites
        • *
        • http.proxyHost
        • *
        • http.proxyPort
        • + *
        • https.proxyHost
        • + *
        • https.proxyPort
        • *
        • http.nonProxyHosts
        • *
        • http.keepAlive
        • *
        • http.maxConnections
        • From 8c4e081ecd02e575dff2ab4172962c96846ae8f7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 26 Nov 2017 16:47:29 +0100 Subject: [PATCH 158/204] HTTPCLIENT-1883: SystemDefaultCredentialsProvider to use https.proxy* system properties for origins with port 443 --- .../SystemDefaultCredentialsProvider.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index 9473ab257d..f977d05298 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -87,17 +87,13 @@ public void setCredentials(final AuthScope authscope, final Credentials credenti } private static PasswordAuthentication getSystemCreds( + final String protocol, final AuthScope authscope, final Authenticator.RequestorType requestorType) { - final String hostname = authscope.getHost(); - final int port = authscope.getPort(); - final HttpHost origin = authscope.getOrigin(); - final String protocol = origin != null ? origin.getSchemeName() : - (port == 443 ? "https" : "http"); return Authenticator.requestPasswordAuthentication( - hostname, + authscope.getHost(), null, - port, + authscope.getPort(), protocol, null, translateScheme(authscope.getScheme()), @@ -114,21 +110,23 @@ public Credentials getCredentials(final AuthScope authscope) { } final String host = authscope.getHost(); if (host != null) { - PasswordAuthentication systemcreds = getSystemCreds(authscope, Authenticator.RequestorType.SERVER); + final HttpHost origin = authscope.getOrigin(); + final String protocol = origin != null ? origin.getSchemeName() : (origin.getPort() == 443 ? "https" : "http"); + PasswordAuthentication systemcreds = getSystemCreds(protocol, authscope, Authenticator.RequestorType.SERVER); if (systemcreds == null) { - systemcreds = getSystemCreds(authscope, Authenticator.RequestorType.PROXY); + systemcreds = getSystemCreds(protocol, authscope, Authenticator.RequestorType.PROXY); } if (systemcreds == null) { - final String proxyHost = System.getProperty("http.proxyHost"); + final String proxyHost = System.getProperty(protocol + ".proxyHost"); if (proxyHost != null) { - final String proxyPort = System.getProperty("http.proxyPort"); + final String proxyPort = System.getProperty(protocol + ".proxyPort"); if (proxyPort != null) { try { final AuthScope systemScope = new AuthScope(proxyHost, Integer.parseInt(proxyPort)); if (authscope.match(systemScope) >= 0) { - final String proxyUser = System.getProperty("http.proxyUser"); + final String proxyUser = System.getProperty(protocol + ".proxyUser"); if (proxyUser != null) { - final String proxyPassword = System.getProperty("http.proxyPassword"); + final String proxyPassword = System.getProperty(protocol + ".proxyPassword"); systemcreds = new PasswordAuthentication(proxyUser, proxyPassword != null ? proxyPassword.toCharArray() : new char[] {}); } } From 721618c243f720107653e132ea07f471864c0377 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 27 Nov 2017 10:29:58 +0100 Subject: [PATCH 159/204] Updated release notes for HttpClient 4.5.4 release --- RELEASE_NOTES.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 30bb4e6802..3a06c01048 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -8,9 +8,37 @@ Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- +* [HTTPCLIENT-1883] SystemDefaultCredentialsProvider to use https.proxy* system properties + for origins with port 443. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1881] Allow truncated NTLM packets to work with this client. + Contributed by Karl Wright + +* [HTTPCLIENT-1855] Disabled caching of DIGEST auth scheme instances due to unreliability of nonce counter + when the auth cache is shared by multiple sessions. + Contributed by Oleg Kalnichevski + +* BasicCookieStore uses a ReentrantReadWriteLock to avoid synchronization on #getCookies/#toString + while maintaining thread safety. + Contributed by Carter Kozak + * [HTTPCLIENT-1865] DefaultServiceUnavailableRetryStrategy does not respect HttpEntity#isRepeatable. Contributed by Tomas Celaya +* [HTTPCLIENT-1859] Encode Content-Disposition name and filename elements appropriately. + Contributed by Karl Wright + +* Avoid fetching the cached entity twice on cache hit. + Contributed by Leandro Nunes + +* [HTTPCLIENT-1835] #evictExpiredConnections no longer causes the #evictIdleConnections behaviour + to be implicitly enabled. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1831= URIBuilder should not prepend a leading slash to relative URIs. + Contributed by Oleg Kalnichevski + * [HTTPCLIENT-1833] Fix Windows Negotiate-NTLM handling of proxies. Contributed by Roman Stoffel From cd166a737cd3f61ba0022012e2a02dd93e22110b Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 27 Nov 2017 10:36:12 +0100 Subject: [PATCH 160/204] HttpClient 4.5.4 release --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- .../entity/DeflateInputStreamFactory.java | 126 ++++++++--------- .../client/entity/GZIPInputStreamFactory.java | 128 +++++++++--------- .../http/conn/ssl/TrustAllStrategy.java | 96 ++++++------- .../http/impl/auth/CredSspSchemeFactory.java | 88 ++++++------ httpmime/pom.xml | 2 +- pom.xml | 4 +- 11 files changed, 227 insertions(+), 227 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 1f2f217a32..82c9c65075 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4-SNAPSHOT + 4.5.4 fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 1f4ffad26e..8f2494663b 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4-SNAPSHOT + 4.5.4 httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 78f97ec9a7..10f0d6dded 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4-SNAPSHOT + 4.5.4 httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index a87ac878e6..3e632119bc 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4-SNAPSHOT + 4.5.4 httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 3a6b0c843f..565285c5fe 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4-SNAPSHOT + 4.5.4 httpclient Apache HttpClient diff --git a/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java index 3853efea0d..dfdefda034 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/DeflateInputStreamFactory.java @@ -1,63 +1,63 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.client.entity; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.http.annotation.Contract; -import org.apache.http.annotation.ThreadingBehavior; - -/** - * {@link InputStreamFactory} for handling Deflate Content Coded responses. - * - * @since 4.5.4 - */ -@Contract(threading = ThreadingBehavior.IMMUTABLE) -public class DeflateInputStreamFactory implements InputStreamFactory { - - /** - * Singleton instance. - */ - private static final DeflateInputStreamFactory INSTANCE = new DeflateInputStreamFactory(); - - /** - * Gets the singleton instance. - * - * @return the singleton instance. - */ - public static DeflateInputStreamFactory getInstance() { - return INSTANCE; - } - - @Override - public InputStream create(final InputStream inputStream) throws IOException { - return new DeflateInputStream(inputStream); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.entity; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; + +/** + * {@link InputStreamFactory} for handling Deflate Content Coded responses. + * + * @since 4.5.4 + */ +@Contract(threading = ThreadingBehavior.IMMUTABLE) +public class DeflateInputStreamFactory implements InputStreamFactory { + + /** + * Singleton instance. + */ + private static final DeflateInputStreamFactory INSTANCE = new DeflateInputStreamFactory(); + + /** + * Gets the singleton instance. + * + * @return the singleton instance. + */ + public static DeflateInputStreamFactory getInstance() { + return INSTANCE; + } + + @Override + public InputStream create(final InputStream inputStream) throws IOException { + return new DeflateInputStream(inputStream); + } + +} diff --git a/httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java b/httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java index f52fd12e8c..787b93726a 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/GZIPInputStreamFactory.java @@ -1,64 +1,64 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.client.entity; - -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.GZIPInputStream; - -import org.apache.http.annotation.Contract; -import org.apache.http.annotation.ThreadingBehavior; - -/** - * {@link InputStreamFactory} for handling GZIPContent Coded responses. - * - * @since 4.5.4 - */ -@Contract(threading = ThreadingBehavior.IMMUTABLE) -public class GZIPInputStreamFactory implements InputStreamFactory { - - /** - * Singleton instance. - */ - private static final GZIPInputStreamFactory INSTANCE = new GZIPInputStreamFactory(); - - /** - * Gets the singleton instance. - * - * @return the singleton instance. - */ - public static GZIPInputStreamFactory getInstance() { - return INSTANCE; - } - - @Override - public InputStream create(final InputStream inputStream) throws IOException { - return new GZIPInputStream(inputStream); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.client.entity; + +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.GZIPInputStream; + +import org.apache.http.annotation.Contract; +import org.apache.http.annotation.ThreadingBehavior; + +/** + * {@link InputStreamFactory} for handling GZIPContent Coded responses. + * + * @since 4.5.4 + */ +@Contract(threading = ThreadingBehavior.IMMUTABLE) +public class GZIPInputStreamFactory implements InputStreamFactory { + + /** + * Singleton instance. + */ + private static final GZIPInputStreamFactory INSTANCE = new GZIPInputStreamFactory(); + + /** + * Gets the singleton instance. + * + * @return the singleton instance. + */ + public static GZIPInputStreamFactory getInstance() { + return INSTANCE; + } + + @Override + public InputStream create(final InputStream inputStream) throws IOException { + return new GZIPInputStream(inputStream); + } + +} diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java b/httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java index d492404e08..3857f530b8 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/TrustAllStrategy.java @@ -1,48 +1,48 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.conn.ssl; - -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -/** - * A trust strategy that accepts all certificates as trusted. Verification of - * all other certificates is done by the trust manager configured in the SSL - * context. - * - * @since 4.5.4 - */ -public class TrustAllStrategy implements TrustStrategy { - - public static final TrustAllStrategy INSTANCE = new TrustAllStrategy(); - - @Override - public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { - return true; - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.conn.ssl; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * A trust strategy that accepts all certificates as trusted. Verification of + * all other certificates is done by the trust manager configured in the SSL + * context. + * + * @since 4.5.4 + */ +public class TrustAllStrategy implements TrustStrategy { + + public static final TrustAllStrategy INSTANCE = new TrustAllStrategy(); + + @Override + public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { + return true; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java index 309101bde6..3953b57583 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java @@ -1,44 +1,44 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.impl.auth; - - -import org.apache.http.auth.AuthScheme; -import org.apache.http.auth.AuthSchemeProvider; -import org.apache.http.protocol.HttpContext; - - -public class CredSspSchemeFactory implements AuthSchemeProvider -{ - - @Override - public AuthScheme create( final HttpContext context ) - { - return new CredSspScheme(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.auth; + + +import org.apache.http.auth.AuthScheme; +import org.apache.http.auth.AuthSchemeProvider; +import org.apache.http.protocol.HttpContext; + + +public class CredSspSchemeFactory implements AuthSchemeProvider +{ + + @Override + public AuthScheme create( final HttpContext context ) + { + return new CredSspScheme(); + } +} diff --git a/httpmime/pom.xml b/httpmime/pom.xml index 8130d92559..37b9b38a76 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4-SNAPSHOT + 4.5.4 httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 2951041a58..8c554ceccf 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.4-SNAPSHOT + 4.5.4 Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 @@ -61,7 +61,7 @@ scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 4.5.x + 4.5.4 From a077bc6ab86a47ef46f6ee21034ee2a374d24a96 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 30 Nov 2017 11:27:42 +0100 Subject: [PATCH 161/204] Upgraded HttpClient version to 4.5.5-SNAPSHOT --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 82c9c65075..c906c70c25 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4 + 4.5.5-SNAPSHOT fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 8f2494663b..9d0d0fabf3 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4 + 4.5.5-SNAPSHOT httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 10f0d6dded..d46b1cd13a 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4 + 4.5.5-SNAPSHOT httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index 3e632119bc..ef09a0670f 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4 + 4.5.5-SNAPSHOT httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 565285c5fe..320ce5ea7a 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4 + 4.5.5-SNAPSHOT httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index 37b9b38a76..f6184f0d5d 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.4 + 4.5.5-SNAPSHOT httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 8c554ceccf..3dbf6cdb66 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.4 + 4.5.5-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 @@ -61,7 +61,7 @@ scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 4.5.4 + 4.5.5-SNAPSHOT From 3af6fea9fab5c69612ccdbf856d4e3ed3cafd778 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 30 Nov 2017 12:26:42 -0700 Subject: [PATCH 162/204] Add slot for 4.5.5. --- RELEASE_NOTES.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 3a06c01048..4ebe9166f4 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,16 @@ +Release 4.5.5 +------------------- + +HttpClient 4.5.5 (GA) is a maintenance release that fixes a number of defects found since 4.5.4. + +Please note that as of 4.4 HttpClient requires Java 1.6 or newer. + +* [HTTPCLIENT-] ... + Contributed by X + +Changelog: +------------------- + Release 4.5.4 ------------------- From 3689823d1cd42f0b2d87f73d614483ae37504a70 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 30 Nov 2017 13:44:21 -0700 Subject: [PATCH 163/204] [HTTPCLIENT-1886] Update HttpClient 4.5.x from HttpCore 4.4.7 to 4.4.8. --- RELEASE_NOTES.txt | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 4ebe9166f4..2c2be1bf51 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -5,8 +5,8 @@ HttpClient 4.5.5 (GA) is a maintenance release that fixes a number of defects fo Please note that as of 4.4 HttpClient requires Java 1.6 or newer. -* [HTTPCLIENT-] ... - Contributed by X +* [HTTPCLIENT-1886] Update HttpClient 4.5.x from HttpCore 4.4.7 to 4.4.8 + Contributed by Gary Gregory Changelog: ------------------- diff --git a/pom.xml b/pom.xml index 3dbf6cdb66..6776d50d8e 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 1.6 1.6 - 4.4.7 + 4.4.8 1.2 1.10 2.6.11 From ea73f439e90dfda943b5d5e7df3cb26ecdfc158a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 30 Nov 2017 13:44:40 -0700 Subject: [PATCH 164/204] [HTTPCLIENT-1886] Update HttpClient 4.5.x from HttpCore 4.4.7 to 4.4.8. --- RELEASE_NOTES.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 2c2be1bf51..0f79d0d9f2 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -5,11 +5,12 @@ HttpClient 4.5.5 (GA) is a maintenance release that fixes a number of defects fo Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Changelog: +------------------- + * [HTTPCLIENT-1886] Update HttpClient 4.5.x from HttpCore 4.4.7 to 4.4.8 Contributed by Gary Gregory -Changelog: -------------------- Release 4.5.4 ------------------- From 5bed670873a2e197bc047737d2f0f4518ab94524 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 5 Dec 2017 09:57:34 +0100 Subject: [PATCH 165/204] HTTPCLIENT-1888: Regression in SystemDefaultCredentialsProvider#getCredentials causing NPE --- .../apache/http/impl/client/AuthenticationStrategyImpl.java | 3 +-- .../http/impl/client/SystemDefaultCredentialsProvider.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java index 4ca17c37f0..7c059d2080 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java @@ -190,8 +190,7 @@ public Queue select( authScheme.processChallenge(challenge); final AuthScope authScope = new AuthScope( - authhost.getHostName(), - authhost.getPort(), + authhost, authScheme.getRealm(), authScheme.getSchemeName()); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index f977d05298..122a85995c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -111,7 +111,7 @@ public Credentials getCredentials(final AuthScope authscope) { final String host = authscope.getHost(); if (host != null) { final HttpHost origin = authscope.getOrigin(); - final String protocol = origin != null ? origin.getSchemeName() : (origin.getPort() == 443 ? "https" : "http"); + final String protocol = origin != null ? origin.getSchemeName() : (authscope.getPort() == 443 ? "https" : "http"); PasswordAuthentication systemcreds = getSystemCreds(protocol, authscope, Authenticator.RequestorType.SERVER); if (systemcreds == null) { systemcreds = getSystemCreds(protocol, authscope, Authenticator.RequestorType.PROXY); From 817d57a208214d9ad3c01442aec0f9bc452b887e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 6 Dec 2017 09:28:30 -0700 Subject: [PATCH 166/204] Replace use of String.indexOf(String) for strings of length one with indexOf(char) --- .../apache/http/impl/auth/NTLMEngineImpl.java | 4204 ++++++++--------- 1 file changed, 2102 insertions(+), 2102 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 6ed5c0ecfa..7e8eb7eac2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -1,2102 +1,2102 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.impl.auth; - -import java.nio.charset.Charset; -import org.apache.http.Consts; -import java.security.Key; -import java.security.MessageDigest; -import java.util.Arrays; -import java.util.Locale; -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.Certificate; - -import org.apache.commons.codec.binary.Base64; - -/** - * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM - * authentication protocol. - * - * @since 4.1 - */ -final class NTLMEngineImpl implements NTLMEngine { - - /** Unicode encoding */ - private static final Charset UNICODE_LITTLE_UNMARKED = Charset.forName("UnicodeLittleUnmarked"); - /** Character encoding */ - private static final Charset DEFAULT_CHARSET = Consts.ASCII; - - // Flags we use; descriptions according to: - // http://davenport.sourceforge.net/ntlm.html - // and - // http://msdn.microsoft.com/en-us/library/cc236650%28v=prot.20%29.aspx - // [MS-NLMP] section 2.2.2.5 - static final int FLAG_REQUEST_UNICODE_ENCODING = 0x00000001; // Unicode string encoding requested - static final int FLAG_REQUEST_OEM_ENCODING = 0x00000002; // OEM string encoding requested - static final int FLAG_REQUEST_TARGET = 0x00000004; // Requests target field - static final int FLAG_REQUEST_SIGN = 0x00000010; // Requests all messages have a signature attached, in NEGOTIATE message. - static final int FLAG_REQUEST_SEAL = 0x00000020; // Request key exchange for message confidentiality in NEGOTIATE message. MUST be used in conjunction with 56BIT. - static final int FLAG_REQUEST_LAN_MANAGER_KEY = 0x00000080; // Request Lan Manager key instead of user session key - static final int FLAG_REQUEST_NTLMv1 = 0x00000200; // Request NTLMv1 security. MUST be set in NEGOTIATE and CHALLENGE both - static final int FLAG_DOMAIN_PRESENT = 0x00001000; // Domain is present in message - static final int FLAG_WORKSTATION_PRESENT = 0x00002000; // Workstation is present in message - static final int FLAG_REQUEST_ALWAYS_SIGN = 0x00008000; // Requests a signature block on all messages. Overridden by REQUEST_SIGN and REQUEST_SEAL. - static final int FLAG_REQUEST_NTLM2_SESSION = 0x00080000; // From server in challenge, requesting NTLM2 session security - static final int FLAG_REQUEST_VERSION = 0x02000000; // Request protocol version - static final int FLAG_TARGETINFO_PRESENT = 0x00800000; // From server in challenge message, indicating targetinfo is present - static final int FLAG_REQUEST_128BIT_KEY_EXCH = 0x20000000; // Request explicit 128-bit key exchange - static final int FLAG_REQUEST_EXPLICIT_KEY_EXCH = 0x40000000; // Request explicit key exchange - static final int FLAG_REQUEST_56BIT_ENCRYPTION = 0x80000000; // Must be used in conjunction with SEAL - - // Attribute-value identifiers (AvId) - // according to [MS-NLMP] section 2.2.2.1 - static final int MSV_AV_EOL = 0x0000; // Indicates that this is the last AV_PAIR in the list. - static final int MSV_AV_NB_COMPUTER_NAME = 0x0001; // The server's NetBIOS computer name. - static final int MSV_AV_NB_DOMAIN_NAME = 0x0002; // The server's NetBIOS domain name. - static final int MSV_AV_DNS_COMPUTER_NAME = 0x0003; // The fully qualified domain name (FQDN) of the computer. - static final int MSV_AV_DNS_DOMAIN_NAME = 0x0004; // The FQDN of the domain. - static final int MSV_AV_DNS_TREE_NAME = 0x0005; // The FQDN of the forest. - static final int MSV_AV_FLAGS = 0x0006; // A 32-bit value indicating server or client configuration. - static final int MSV_AV_TIMESTAMP = 0x0007; // server local time - static final int MSV_AV_SINGLE_HOST = 0x0008; // A Single_Host_Data structure. - static final int MSV_AV_TARGET_NAME = 0x0009; // The SPN of the target server. - static final int MSV_AV_CHANNEL_BINDINGS = 0x000A; // A channel bindings hash. - - static final int MSV_AV_FLAGS_ACCOUNT_AUTH_CONSTAINED = 0x00000001; // Indicates to the client that the account authentication is constrained. - static final int MSV_AV_FLAGS_MIC = 0x00000002; // Indicates that the client is providing message integrity in the MIC field in the AUTHENTICATE_MESSAGE. - static final int MSV_AV_FLAGS_UNTRUSTED_TARGET_SPN = 0x00000004; // Indicates that the client is providing a target SPN generated from an untrusted source. - - /** Secure random generator */ - private static final java.security.SecureRandom RND_GEN; - static { - java.security.SecureRandom rnd = null; - try { - rnd = java.security.SecureRandom.getInstance("SHA1PRNG"); - } catch (final Exception ignore) { - } - RND_GEN = rnd; - } - - /** The signature string as bytes in the default encoding */ - private static final byte[] SIGNATURE = getNullTerminatedAsciiString("NTLMSSP"); - - // Key derivation magic strings for the SIGNKEY algorithm defined in - // [MS-NLMP] section 3.4.5.2 - private static final byte[] SIGN_MAGIC_SERVER = getNullTerminatedAsciiString( - "session key to server-to-client signing key magic constant"); - private static final byte[] SIGN_MAGIC_CLIENT = getNullTerminatedAsciiString( - "session key to client-to-server signing key magic constant"); - private static final byte[] SEAL_MAGIC_SERVER = getNullTerminatedAsciiString( - "session key to server-to-client sealing key magic constant"); - private static final byte[] SEAL_MAGIC_CLIENT = getNullTerminatedAsciiString( - "session key to client-to-server sealing key magic constant"); - - // prefix for GSS API channel binding - private static final byte[] MAGIC_TLS_SERVER_ENDPOINT = "tls-server-end-point:".getBytes(Consts.ASCII); - - private static byte[] getNullTerminatedAsciiString( final String source ) - { - final byte[] bytesWithoutNull = source.getBytes(Consts.ASCII); - final byte[] target = new byte[bytesWithoutNull.length + 1]; - System.arraycopy(bytesWithoutNull, 0, target, 0, bytesWithoutNull.length); - target[bytesWithoutNull.length] = (byte) 0x00; - return target; - } - - private static final String TYPE_1_MESSAGE = new Type1Message().getResponse(); - - NTLMEngineImpl() { - } - - /** - * Creates the first message (type 1 message) in the NTLM authentication - * sequence. This message includes the user name, domain and host for the - * authentication session. - * - * @param host - * the computer name of the host requesting authentication. - * @param domain - * The domain to authenticate with. - * @return String the message to add to the HTTP request header. - */ - static String getType1Message(final String host, final String domain) { - // For compatibility reason do not include domain and host in type 1 message - //return new Type1Message(domain, host).getResponse(); - return TYPE_1_MESSAGE; - } - - /** - * Creates the type 3 message using the given server nonce. The type 3 - * message includes all the information for authentication, host, domain, - * username and the result of encrypting the nonce sent by the server using - * the user's password as the key. - * - * @param user - * The user name. This should not include the domain name. - * @param password - * The password. - * @param host - * The host that is originating the authentication request. - * @param domain - * The domain to authenticate within. - * @param nonce - * the 8 byte array the server sent. - * @return The type 3 message. - * @throws NTLMEngineException - * If {@encrypt(byte[],byte[])} fails. - */ - static String getType3Message(final String user, final String password, final String host, final String domain, - final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation) - throws NTLMEngineException { - return new Type3Message(domain, host, user, password, nonce, type2Flags, target, - targetInformation).getResponse(); - } - - /** - * Creates the type 3 message using the given server nonce. The type 3 - * message includes all the information for authentication, host, domain, - * username and the result of encrypting the nonce sent by the server using - * the user's password as the key. - * - * @param user - * The user name. This should not include the domain name. - * @param password - * The password. - * @param host - * The host that is originating the authentication request. - * @param domain - * The domain to authenticate within. - * @param nonce - * the 8 byte array the server sent. - * @return The type 3 message. - * @throws NTLMEngineException - * If {@encrypt(byte[],byte[])} fails. - */ - static String getType3Message(final String user, final String password, final String host, final String domain, - final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation, - final Certificate peerServerCertificate, final byte[] type1Message, final byte[] type2Message) - throws NTLMEngineException { - return new Type3Message(domain, host, user, password, nonce, type2Flags, target, - targetInformation, peerServerCertificate, type1Message, type2Message).getResponse(); - } - - private static int readULong(final byte[] src, final int index) throws NTLMEngineException { - if (src.length < index + 4) { - return 0; - } - return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) - | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); - } - - private static int readUShort(final byte[] src, final int index) throws NTLMEngineException { - if (src.length < index + 2) { - return 0; - } - return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); - } - - private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException { - final int length = readUShort(src, index); - final int offset = readULong(src, index + 4); - if (src.length < offset + length) { - return new byte[length]; - } - final byte[] buffer = new byte[length]; - System.arraycopy(src, offset, buffer, 0, length); - return buffer; - } - - /** Calculate a challenge block */ - private static byte[] makeRandomChallenge(final Random random) throws NTLMEngineException { - final byte[] rval = new byte[8]; - synchronized (random) { - random.nextBytes(rval); - } - return rval; - } - - /** Calculate a 16-byte secondary key */ - private static byte[] makeSecondaryKey(final Random random) throws NTLMEngineException { - final byte[] rval = new byte[16]; - synchronized (random) { - random.nextBytes(rval); - } - return rval; - } - - protected static class CipherGen { - - protected final Random random; - protected final long currentTime; - - protected final String domain; - protected final String user; - protected final String password; - protected final byte[] challenge; - protected final String target; - protected final byte[] targetInformation; - - // Information we can generate but may be passed in (for testing) - protected byte[] clientChallenge; - protected byte[] clientChallenge2; - protected byte[] secondaryKey; - protected byte[] timestamp; - - // Stuff we always generate - protected byte[] lmHash = null; - protected byte[] lmResponse = null; - protected byte[] ntlmHash = null; - protected byte[] ntlmResponse = null; - protected byte[] ntlmv2Hash = null; - protected byte[] lmv2Hash = null; - protected byte[] lmv2Response = null; - protected byte[] ntlmv2Blob = null; - protected byte[] ntlmv2Response = null; - protected byte[] ntlm2SessionResponse = null; - protected byte[] lm2SessionResponse = null; - protected byte[] lmUserSessionKey = null; - protected byte[] ntlmUserSessionKey = null; - protected byte[] ntlmv2UserSessionKey = null; - protected byte[] ntlm2SessionResponseUserSessionKey = null; - protected byte[] lanManagerSessionKey = null; - - @Deprecated - public CipherGen(final String domain, final String user, final String password, - final byte[] challenge, final String target, final byte[] targetInformation, - final byte[] clientChallenge, final byte[] clientChallenge2, - final byte[] secondaryKey, final byte[] timestamp) { - this(RND_GEN, System.currentTimeMillis(), - domain, user, password, challenge, target, targetInformation, - clientChallenge, clientChallenge2, - secondaryKey, timestamp); - } - - public CipherGen(final Random random, final long currentTime, - final String domain, final String user, final String password, - final byte[] challenge, final String target, final byte[] targetInformation, - final byte[] clientChallenge, final byte[] clientChallenge2, - final byte[] secondaryKey, final byte[] timestamp) { - this.random = random; - this.currentTime = currentTime; - - this.domain = domain; - this.target = target; - this.user = user; - this.password = password; - this.challenge = challenge; - this.targetInformation = targetInformation; - this.clientChallenge = clientChallenge; - this.clientChallenge2 = clientChallenge2; - this.secondaryKey = secondaryKey; - this.timestamp = timestamp; - } - - @Deprecated - public CipherGen(final String domain, - final String user, - final String password, - final byte[] challenge, - final String target, - final byte[] targetInformation) { - this(RND_GEN, System.currentTimeMillis(), domain, user, password, challenge, target, targetInformation); - } - - public CipherGen(final Random random, final long currentTime, - final String domain, - final String user, - final String password, - final byte[] challenge, - final String target, - final byte[] targetInformation) { - this(random, currentTime, domain, user, password, challenge, target, targetInformation, null, null, null, null); - } - - /** Calculate and return client challenge */ - public byte[] getClientChallenge() - throws NTLMEngineException { - if (clientChallenge == null) { - clientChallenge = makeRandomChallenge(random); - } - return clientChallenge; - } - - /** Calculate and return second client challenge */ - public byte[] getClientChallenge2() - throws NTLMEngineException { - if (clientChallenge2 == null) { - clientChallenge2 = makeRandomChallenge(random); - } - return clientChallenge2; - } - - /** Calculate and return random secondary key */ - public byte[] getSecondaryKey() - throws NTLMEngineException { - if (secondaryKey == null) { - secondaryKey = makeSecondaryKey(random); - } - return secondaryKey; - } - - /** Calculate and return the LMHash */ - public byte[] getLMHash() - throws NTLMEngineException { - if (lmHash == null) { - lmHash = lmHash(password); - } - return lmHash; - } - - /** Calculate and return the LMResponse */ - public byte[] getLMResponse() - throws NTLMEngineException { - if (lmResponse == null) { - lmResponse = lmResponse(getLMHash(),challenge); - } - return lmResponse; - } - - /** Calculate and return the NTLMHash */ - public byte[] getNTLMHash() - throws NTLMEngineException { - if (ntlmHash == null) { - ntlmHash = ntlmHash(password); - } - return ntlmHash; - } - - /** Calculate and return the NTLMResponse */ - public byte[] getNTLMResponse() - throws NTLMEngineException { - if (ntlmResponse == null) { - ntlmResponse = lmResponse(getNTLMHash(),challenge); - } - return ntlmResponse; - } - - /** Calculate the LMv2 hash */ - public byte[] getLMv2Hash() - throws NTLMEngineException { - if (lmv2Hash == null) { - lmv2Hash = lmv2Hash(domain, user, getNTLMHash()); - } - return lmv2Hash; - } - - /** Calculate the NTLMv2 hash */ - public byte[] getNTLMv2Hash() - throws NTLMEngineException { - if (ntlmv2Hash == null) { - ntlmv2Hash = ntlmv2Hash(domain, user, getNTLMHash()); - } - return ntlmv2Hash; - } - - /** Calculate a timestamp */ - public byte[] getTimestamp() { - if (timestamp == null) { - long time = this.currentTime; - time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch. - time *= 10000; // tenths of a microsecond. - // convert to little-endian byte array. - timestamp = new byte[8]; - for (int i = 0; i < 8; i++) { - timestamp[i] = (byte) time; - time >>>= 8; - } - } - return timestamp; - } - - /** Calculate the NTLMv2Blob */ - public byte[] getNTLMv2Blob() - throws NTLMEngineException { - if (ntlmv2Blob == null) { - ntlmv2Blob = createBlob(getClientChallenge2(), targetInformation, getTimestamp()); - } - return ntlmv2Blob; - } - - /** Calculate the NTLMv2Response */ - public byte[] getNTLMv2Response() - throws NTLMEngineException { - if (ntlmv2Response == null) { - ntlmv2Response = lmv2Response(getNTLMv2Hash(),challenge,getNTLMv2Blob()); - } - return ntlmv2Response; - } - - /** Calculate the LMv2Response */ - public byte[] getLMv2Response() - throws NTLMEngineException { - if (lmv2Response == null) { - lmv2Response = lmv2Response(getLMv2Hash(),challenge,getClientChallenge()); - } - return lmv2Response; - } - - /** Get NTLM2SessionResponse */ - public byte[] getNTLM2SessionResponse() - throws NTLMEngineException { - if (ntlm2SessionResponse == null) { - ntlm2SessionResponse = ntlm2SessionResponse(getNTLMHash(),challenge,getClientChallenge()); - } - return ntlm2SessionResponse; - } - - /** Calculate and return LM2 session response */ - public byte[] getLM2SessionResponse() - throws NTLMEngineException { - if (lm2SessionResponse == null) { - final byte[] clntChallenge = getClientChallenge(); - lm2SessionResponse = new byte[24]; - System.arraycopy(clntChallenge, 0, lm2SessionResponse, 0, clntChallenge.length); - Arrays.fill(lm2SessionResponse, clntChallenge.length, lm2SessionResponse.length, (byte) 0x00); - } - return lm2SessionResponse; - } - - /** Get LMUserSessionKey */ - public byte[] getLMUserSessionKey() - throws NTLMEngineException { - if (lmUserSessionKey == null) { - lmUserSessionKey = new byte[16]; - System.arraycopy(getLMHash(), 0, lmUserSessionKey, 0, 8); - Arrays.fill(lmUserSessionKey, 8, 16, (byte) 0x00); - } - return lmUserSessionKey; - } - - /** Get NTLMUserSessionKey */ - public byte[] getNTLMUserSessionKey() - throws NTLMEngineException { - if (ntlmUserSessionKey == null) { - final MD4 md4 = new MD4(); - md4.update(getNTLMHash()); - ntlmUserSessionKey = md4.getOutput(); - } - return ntlmUserSessionKey; - } - - /** GetNTLMv2UserSessionKey */ - public byte[] getNTLMv2UserSessionKey() - throws NTLMEngineException { - if (ntlmv2UserSessionKey == null) { - final byte[] ntlmv2hash = getNTLMv2Hash(); - final byte[] truncatedResponse = new byte[16]; - System.arraycopy(getNTLMv2Response(), 0, truncatedResponse, 0, 16); - ntlmv2UserSessionKey = hmacMD5(truncatedResponse, ntlmv2hash); - } - return ntlmv2UserSessionKey; - } - - /** Get NTLM2SessionResponseUserSessionKey */ - public byte[] getNTLM2SessionResponseUserSessionKey() - throws NTLMEngineException { - if (ntlm2SessionResponseUserSessionKey == null) { - final byte[] ntlm2SessionResponseNonce = getLM2SessionResponse(); - final byte[] sessionNonce = new byte[challenge.length + ntlm2SessionResponseNonce.length]; - System.arraycopy(challenge, 0, sessionNonce, 0, challenge.length); - System.arraycopy(ntlm2SessionResponseNonce, 0, sessionNonce, challenge.length, ntlm2SessionResponseNonce.length); - ntlm2SessionResponseUserSessionKey = hmacMD5(sessionNonce,getNTLMUserSessionKey()); - } - return ntlm2SessionResponseUserSessionKey; - } - - /** Get LAN Manager session key */ - public byte[] getLanManagerSessionKey() - throws NTLMEngineException { - if (lanManagerSessionKey == null) { - try { - final byte[] keyBytes = new byte[14]; - System.arraycopy(getLMHash(), 0, keyBytes, 0, 8); - Arrays.fill(keyBytes, 8, keyBytes.length, (byte)0xbd); - final Key lowKey = createDESKey(keyBytes, 0); - final Key highKey = createDESKey(keyBytes, 7); - final byte[] truncatedResponse = new byte[8]; - System.arraycopy(getLMResponse(), 0, truncatedResponse, 0, truncatedResponse.length); - Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowPart = des.doFinal(truncatedResponse); - des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highPart = des.doFinal(truncatedResponse); - lanManagerSessionKey = new byte[16]; - System.arraycopy(lowPart, 0, lanManagerSessionKey, 0, lowPart.length); - System.arraycopy(highPart, 0, lanManagerSessionKey, lowPart.length, highPart.length); - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - return lanManagerSessionKey; - } - } - - /** Calculates HMAC-MD5 */ - static byte[] hmacMD5(final byte[] value, final byte[] key) - throws NTLMEngineException { - final HMACMD5 hmacMD5 = new HMACMD5(key); - hmacMD5.update(value); - return hmacMD5.getOutput(); - } - - /** Calculates RC4 */ - static byte[] RC4(final byte[] value, final byte[] key) - throws NTLMEngineException { - try { - final Cipher rc4 = Cipher.getInstance("RC4"); - rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC4")); - return rc4.doFinal(value); - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Calculates the NTLM2 Session Response for the given challenge, using the - * specified password and client challenge. - * - * @return The NTLM2 Session Response. This is placed in the NTLM response - * field of the Type 3 message; the LM response field contains the - * client challenge, null-padded to 24 bytes. - */ - static byte[] ntlm2SessionResponse(final byte[] ntlmHash, final byte[] challenge, - final byte[] clientChallenge) throws NTLMEngineException { - try { - final MessageDigest md5 = getMD5(); - md5.update(challenge); - md5.update(clientChallenge); - final byte[] digest = md5.digest(); - - final byte[] sessionHash = new byte[8]; - System.arraycopy(digest, 0, sessionHash, 0, 8); - return lmResponse(ntlmHash, sessionHash); - } catch (final Exception e) { - if (e instanceof NTLMEngineException) { - throw (NTLMEngineException) e; - } - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Creates the LM Hash of the user's password. - * - * @param password - * The password. - * - * @return The LM Hash of the given password, used in the calculation of the - * LM Response. - */ - private static byte[] lmHash(final String password) throws NTLMEngineException { - try { - final byte[] oemPassword = password.toUpperCase(Locale.ROOT).getBytes(Consts.ASCII); - final int length = Math.min(oemPassword.length, 14); - final byte[] keyBytes = new byte[14]; - System.arraycopy(oemPassword, 0, keyBytes, 0, length); - final Key lowKey = createDESKey(keyBytes, 0); - final Key highKey = createDESKey(keyBytes, 7); - final byte[] magicConstant = "KGS!@#$%".getBytes(Consts.ASCII); - final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowHash = des.doFinal(magicConstant); - des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highHash = des.doFinal(magicConstant); - final byte[] lmHash = new byte[16]; - System.arraycopy(lowHash, 0, lmHash, 0, 8); - System.arraycopy(highHash, 0, lmHash, 8, 8); - return lmHash; - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Creates the NTLM Hash of the user's password. - * - * @param password - * The password. - * - * @return The NTLM Hash of the given password, used in the calculation of - * the NTLM Response and the NTLMv2 and LMv2 Hashes. - */ - private static byte[] ntlmHash(final String password) throws NTLMEngineException { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } - final byte[] unicodePassword = password.getBytes(UNICODE_LITTLE_UNMARKED); - final MD4 md4 = new MD4(); - md4.update(unicodePassword); - return md4.getOutput(); - } - - /** - * Creates the LMv2 Hash of the user's password. - * - * @return The LMv2 Hash, used in the calculation of the NTLMv2 and LMv2 - * Responses. - */ - private static byte[] lmv2Hash(final String domain, final String user, final byte[] ntlmHash) - throws NTLMEngineException { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } - final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); - // Upper case username, upper case domain! - hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); - if (domain != null) { - hmacMD5.update(domain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); - } - return hmacMD5.getOutput(); - } - - /** - * Creates the NTLMv2 Hash of the user's password. - * - * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 and LMv2 - * Responses. - */ - private static byte[] ntlmv2Hash(final String domain, final String user, final byte[] ntlmHash) - throws NTLMEngineException { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } - final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); - // Upper case username, mixed case target!! - hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); - if (domain != null) { - hmacMD5.update(domain.getBytes(UNICODE_LITTLE_UNMARKED)); - } - return hmacMD5.getOutput(); - } - - /** - * Creates the LM Response from the given hash and Type 2 challenge. - * - * @param hash - * The LM or NTLM Hash. - * @param challenge - * The server challenge from the Type 2 message. - * - * @return The response (either LM or NTLM, depending on the provided hash). - */ - private static byte[] lmResponse(final byte[] hash, final byte[] challenge) throws NTLMEngineException { - try { - final byte[] keyBytes = new byte[21]; - System.arraycopy(hash, 0, keyBytes, 0, 16); - final Key lowKey = createDESKey(keyBytes, 0); - final Key middleKey = createDESKey(keyBytes, 7); - final Key highKey = createDESKey(keyBytes, 14); - final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowResponse = des.doFinal(challenge); - des.init(Cipher.ENCRYPT_MODE, middleKey); - final byte[] middleResponse = des.doFinal(challenge); - des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highResponse = des.doFinal(challenge); - final byte[] lmResponse = new byte[24]; - System.arraycopy(lowResponse, 0, lmResponse, 0, 8); - System.arraycopy(middleResponse, 0, lmResponse, 8, 8); - System.arraycopy(highResponse, 0, lmResponse, 16, 8); - return lmResponse; - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Creates the LMv2 Response from the given hash, client data, and Type 2 - * challenge. - * - * @param hash - * The NTLMv2 Hash. - * @param clientData - * The client data (blob or client challenge). - * @param challenge - * The server challenge from the Type 2 message. - * - * @return The response (either NTLMv2 or LMv2, depending on the client - * data). - */ - private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData) - throws NTLMEngineException { - final HMACMD5 hmacMD5 = new HMACMD5(hash); - hmacMD5.update(challenge); - hmacMD5.update(clientData); - final byte[] mac = hmacMD5.getOutput(); - final byte[] lmv2Response = new byte[mac.length + clientData.length]; - System.arraycopy(mac, 0, lmv2Response, 0, mac.length); - System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length); - return lmv2Response; - } - - static enum Mode - { - CLIENT, SERVER; - } - - static class Handle - { - final private byte[] exportedSessionKey; - private byte[] signingKey; - private byte[] sealingKey; - private final Cipher rc4; - final Mode mode; - final private boolean isConnection; - int sequenceNumber = 0; - - - Handle( final byte[] exportedSessionKey, final Mode mode, final boolean isConnection ) - throws NTLMEngineException - { - this.exportedSessionKey = exportedSessionKey; - this.isConnection = isConnection; - this.mode = mode; - try - { - final MessageDigest signMd5 = getMD5(); - final MessageDigest sealMd5 = getMD5(); - signMd5.update( exportedSessionKey ); - sealMd5.update( exportedSessionKey ); - if ( mode == Mode.CLIENT ) - { - signMd5.update( SIGN_MAGIC_CLIENT ); - sealMd5.update( SEAL_MAGIC_CLIENT ); - } - else - { - signMd5.update( SIGN_MAGIC_SERVER ); - sealMd5.update( SEAL_MAGIC_SERVER ); - } - signingKey = signMd5.digest(); - sealingKey = sealMd5.digest(); - } - catch ( final Exception e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - rc4 = initCipher(); - } - - public byte[] getSigningKey() - { - return signingKey; - } - - - public byte[] getSealingKey() - { - return sealingKey; - } - - private Cipher initCipher() throws NTLMEngineException - { - final Cipher cipher; - try - { - cipher = Cipher.getInstance( "RC4" ); - if ( mode == Mode.CLIENT ) - { - cipher.init( Cipher.ENCRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); - } - else - { - cipher.init( Cipher.DECRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); - } - } - catch ( final Exception e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - return cipher; - } - - - private void advanceMessageSequence() throws NTLMEngineException - { - if ( !isConnection ) - { - final MessageDigest sealMd5 = getMD5(); - sealMd5.update( sealingKey ); - final byte[] seqNumBytes = new byte[4]; - writeULong( seqNumBytes, sequenceNumber, 0 ); - sealMd5.update( seqNumBytes ); - sealingKey = sealMd5.digest(); - initCipher(); - } - sequenceNumber++; - } - - private byte[] encrypt( final byte[] data ) throws NTLMEngineException - { - return rc4.update( data ); - } - - private byte[] decrypt( final byte[] data ) throws NTLMEngineException - { - return rc4.update( data ); - } - - private byte[] computeSignature( final byte[] message ) throws NTLMEngineException - { - final byte[] sig = new byte[16]; - - // version - sig[0] = 0x01; - sig[1] = 0x00; - sig[2] = 0x00; - sig[3] = 0x00; - - // HMAC (first 8 bytes) - final HMACMD5 hmacMD5 = new HMACMD5( signingKey ); - hmacMD5.update( encodeLong( sequenceNumber ) ); - hmacMD5.update( message ); - final byte[] hmac = hmacMD5.getOutput(); - final byte[] trimmedHmac = new byte[8]; - System.arraycopy( hmac, 0, trimmedHmac, 0, 8 ); - final byte[] encryptedHmac = encrypt( trimmedHmac ); - System.arraycopy( encryptedHmac, 0, sig, 4, 8 ); - - // sequence number - encodeLong( sig, 12, sequenceNumber ); - - return sig; - } - - private boolean validateSignature( final byte[] signature, final byte message[] ) throws NTLMEngineException - { - final byte[] computedSignature = computeSignature( message ); - // log.info( "SSSSS validateSignature("+seqNumber+")\n" - // + " received: " + DebugUtil.dump( signature ) + "\n" - // + " computed: " + DebugUtil.dump( computedSignature ) ); - return Arrays.equals( signature, computedSignature ); - } - - public byte[] signAndEncryptMessage( final byte[] cleartextMessage ) throws NTLMEngineException - { - final byte[] encryptedMessage = encrypt( cleartextMessage ); - final byte[] signature = computeSignature( cleartextMessage ); - final byte[] outMessage = new byte[signature.length + encryptedMessage.length]; - System.arraycopy( signature, 0, outMessage, 0, signature.length ); - System.arraycopy( encryptedMessage, 0, outMessage, signature.length, encryptedMessage.length ); - advanceMessageSequence(); - return outMessage; - } - - public byte[] decryptAndVerifySignedMessage( final byte[] inMessage ) throws NTLMEngineException - { - final byte[] signature = new byte[16]; - System.arraycopy( inMessage, 0, signature, 0, signature.length ); - final byte[] encryptedMessage = new byte[inMessage.length - 16]; - System.arraycopy( inMessage, 16, encryptedMessage, 0, encryptedMessage.length ); - final byte[] cleartextMessage = decrypt( encryptedMessage ); - if ( !validateSignature( signature, cleartextMessage ) ) - { - throw new NTLMEngineException( "Wrong signature" ); - } - advanceMessageSequence(); - return cleartextMessage; - } - - } - - private static byte[] encodeLong( final int value ) - { - final byte[] enc = new byte[4]; - encodeLong( enc, 0, value ); - return enc; - } - - private static void encodeLong( final byte[] buf, final int offset, final int value ) - { - buf[offset + 0] = ( byte ) ( value & 0xff ); - buf[offset + 1] = ( byte ) ( value >> 8 & 0xff ); - buf[offset + 2] = ( byte ) ( value >> 16 & 0xff ); - buf[offset + 3] = ( byte ) ( value >> 24 & 0xff ); - } - - /** - * Creates the NTLMv2 blob from the given target information block and - * client challenge. - * - * @param targetInformation - * The target information block from the Type 2 message. - * @param clientChallenge - * The random 8-byte client challenge. - * - * @return The blob, used in the calculation of the NTLMv2 Response. - */ - private static byte[] createBlob(final byte[] clientChallenge, final byte[] targetInformation, final byte[] timestamp) { - final byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; - final byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8 - + unknown1.length + targetInformation.length + unknown2.length]; - int offset = 0; - System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); - offset += blobSignature.length; - System.arraycopy(reserved, 0, blob, offset, reserved.length); - offset += reserved.length; - System.arraycopy(timestamp, 0, blob, offset, timestamp.length); - offset += timestamp.length; - System.arraycopy(clientChallenge, 0, blob, offset, 8); - offset += 8; - System.arraycopy(unknown1, 0, blob, offset, unknown1.length); - offset += unknown1.length; - System.arraycopy(targetInformation, 0, blob, offset, targetInformation.length); - offset += targetInformation.length; - System.arraycopy(unknown2, 0, blob, offset, unknown2.length); - offset += unknown2.length; - return blob; - } - - /** - * Creates a DES encryption key from the given key material. - * - * @param bytes - * A byte array containing the DES key material. - * @param offset - * The offset in the given byte array at which the 7-byte key - * material starts. - * - * @return A DES encryption key created from the key material starting at - * the specified offset in the given byte array. - */ - private static Key createDESKey(final byte[] bytes, final int offset) { - final byte[] keyBytes = new byte[7]; - System.arraycopy(bytes, offset, keyBytes, 0, 7); - final byte[] material = new byte[8]; - material[0] = keyBytes[0]; - material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); - material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); - material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3); - material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4); - material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5); - material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6); - material[7] = (byte) (keyBytes[6] << 1); - oddParity(material); - return new SecretKeySpec(material, "DES"); - } - - /** - * Applies odd parity to the given byte array. - * - * @param bytes - * The data whose parity bits are to be adjusted for odd parity. - */ - private static void oddParity(final byte[] bytes) { - for (int i = 0; i < bytes.length; i++) { - final byte b = bytes[i]; - final boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) - ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0; - if (needsParity) { - bytes[i] |= (byte) 0x01; - } else { - bytes[i] &= (byte) 0xfe; - } - } - } - - /** - * Find the character set based on the flags. - * @param flags is the flags. - * @return the character set. - */ - private static Charset getCharset(final int flags) throws NTLMEngineException - { - if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { - return DEFAULT_CHARSET; - } else { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException( "Unicode not supported" ); - } - return UNICODE_LITTLE_UNMARKED; - } - } - - /** Strip dot suffix from a name */ - private static String stripDotSuffix(final String value) { - if (value == null) { - return null; - } - final int index = value.indexOf("."); - if (index != -1) { - return value.substring(0, index); - } - return value; - } - - /** Convert host to standard form */ - private static String convertHost(final String host) { - return stripDotSuffix(host); - } - - /** Convert domain to standard form */ - private static String convertDomain(final String domain) { - return stripDotSuffix(domain); - } - - /** NTLM message generation, base class */ - static class NTLMMessage { - /** The current response */ - protected byte[] messageContents = null; - - /** The current output position */ - protected int currentOutputPosition = 0; - - /** Constructor to use when message contents are not yet known */ - NTLMMessage() { - } - - /** Constructor taking a string */ - NTLMMessage(final String messageBody, final int expectedType) throws NTLMEngineException { - this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET)), expectedType); - } - - /** Constructor to use when message bytes are known */ - NTLMMessage(final byte[] message, final int expectedType) throws NTLMEngineException { - messageContents = message; - // Look for NTLM message - if (messageContents.length < SIGNATURE.length) { - throw new NTLMEngineException("NTLM message decoding error - packet too short"); - } - int i = 0; - while (i < SIGNATURE.length) { - if (messageContents[i] != SIGNATURE[i]) { - throw new NTLMEngineException( - "NTLM message expected - instead got unrecognized bytes"); - } - i++; - } - - // Check to be sure there's a type 2 message indicator next - final int type = readULong(SIGNATURE.length); - if (type != expectedType) { - throw new NTLMEngineException("NTLM type " + Integer.toString(expectedType) - + " message expected - instead got type " + Integer.toString(type)); - } - - currentOutputPosition = messageContents.length; - } - - /** - * Get the length of the signature and flags, so calculations can adjust - * offsets accordingly. - */ - protected int getPreambleLength() { - return SIGNATURE.length + 4; - } - - /** Get the message length */ - protected int getMessageLength() { - return currentOutputPosition; - } - - /** Read a byte from a position within the message buffer */ - protected byte readByte(final int position) throws NTLMEngineException { - if (messageContents.length < position + 1) { - throw new NTLMEngineException("NTLM: Message too short"); - } - return messageContents[position]; - } - - /** Read a bunch of bytes from a position in the message buffer */ - protected void readBytes(final byte[] buffer, final int position) throws NTLMEngineException { - if (messageContents.length < position + buffer.length) { - throw new NTLMEngineException("NTLM: Message too short"); - } - System.arraycopy(messageContents, position, buffer, 0, buffer.length); - } - - /** Read a ushort from a position within the message buffer */ - protected int readUShort(final int position) throws NTLMEngineException { - return NTLMEngineImpl.readUShort(messageContents, position); - } - - /** Read a ulong from a position within the message buffer */ - protected int readULong(final int position) throws NTLMEngineException { - return NTLMEngineImpl.readULong(messageContents, position); - } - - /** Read a security buffer from a position within the message buffer */ - protected byte[] readSecurityBuffer(final int position) throws NTLMEngineException { - return NTLMEngineImpl.readSecurityBuffer(messageContents, position); - } - - /** - * Prepares the object to create a response of the given length. - * - * @param maxlength - * the maximum length of the response to prepare, - * including the type and the signature (which this method - * adds). - */ - protected void prepareResponse(final int maxlength, final int messageType) { - messageContents = new byte[maxlength]; - currentOutputPosition = 0; - addBytes(SIGNATURE); - addULong(messageType); - } - - /** - * Adds the given byte to the response. - * - * @param b - * the byte to add. - */ - protected void addByte(final byte b) { - messageContents[currentOutputPosition] = b; - currentOutputPosition++; - } - - /** - * Adds the given bytes to the response. - * - * @param bytes - * the bytes to add. - */ - protected void addBytes(final byte[] bytes) { - if (bytes == null) { - return; - } - for (final byte b : bytes) { - messageContents[currentOutputPosition] = b; - currentOutputPosition++; - } - } - - /** Adds a USHORT to the response */ - protected void addUShort(final int value) { - addByte((byte) (value & 0xff)); - addByte((byte) (value >> 8 & 0xff)); - } - - /** Adds a ULong to the response */ - protected void addULong(final int value) { - addByte((byte) (value & 0xff)); - addByte((byte) (value >> 8 & 0xff)); - addByte((byte) (value >> 16 & 0xff)); - addByte((byte) (value >> 24 & 0xff)); - } - - /** - * Returns the response that has been generated after shrinking the - * array if required and base64 encodes the response. - * - * @return The response as above. - */ - public String getResponse() { - return new String(Base64.encodeBase64(getBytes()), Consts.ASCII); - } - - public byte[] getBytes() { - if (messageContents == null) { - buildMessage(); - } - final byte[] resp; - if ( messageContents.length > currentOutputPosition ) { - final byte[] tmp = new byte[currentOutputPosition]; - System.arraycopy( messageContents, 0, tmp, 0, currentOutputPosition ); - messageContents = tmp; - } - return messageContents; - } - - protected void buildMessage() { - throw new RuntimeException("Message builder not implemented for "+getClass().getName()); - } - } - - /** Type 1 message assembly class */ - static class Type1Message extends NTLMMessage { - - private final byte[] hostBytes; - private final byte[] domainBytes; - private final int flags; - - Type1Message(final String domain, final String host) throws NTLMEngineException { - this(domain, host, null); - } - - Type1Message(final String domain, final String host, final Integer flags) throws NTLMEngineException { - super(); - this.flags = ((flags == null)?getDefaultFlags():flags); - - // Strip off domain name from the host! - final String unqualifiedHost = convertHost(host); - // Use only the base domain name! - final String unqualifiedDomain = convertDomain(domain); - - hostBytes = unqualifiedHost != null ? - unqualifiedHost.getBytes(UNICODE_LITTLE_UNMARKED) : null; - domainBytes = unqualifiedDomain != null ? - unqualifiedDomain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED) : null; - } - - Type1Message() { - super(); - hostBytes = null; - domainBytes = null; - flags = getDefaultFlags(); - } - - private int getDefaultFlags() { - return - //FLAG_WORKSTATION_PRESENT | - //FLAG_DOMAIN_PRESENT | - - // Required flags - //FLAG_REQUEST_LAN_MANAGER_KEY | - FLAG_REQUEST_NTLMv1 | - FLAG_REQUEST_NTLM2_SESSION | - - // Protocol version request - FLAG_REQUEST_VERSION | - - // Recommended privacy settings - FLAG_REQUEST_ALWAYS_SIGN | - //FLAG_REQUEST_SEAL | - //FLAG_REQUEST_SIGN | - - // These must be set according to documentation, based on use of SEAL above - FLAG_REQUEST_128BIT_KEY_EXCH | - FLAG_REQUEST_56BIT_ENCRYPTION | - //FLAG_REQUEST_EXPLICIT_KEY_EXCH | - - FLAG_REQUEST_UNICODE_ENCODING; - - } - - /** - * Getting the response involves building the message before returning - * it - */ - @Override - protected void buildMessage() { - int domainBytesLength = 0; - if ( domainBytes != null ) { - domainBytesLength = domainBytes.length; - } - int hostBytesLength = 0; - if ( hostBytes != null ) { - hostBytesLength = hostBytes.length; - } - - // Now, build the message. Calculate its length first, including - // signature or type. - final int finalLength = 32 + 8 + hostBytesLength + domainBytesLength; - - // Set up the response. This will initialize the signature, message - // type, and flags. - prepareResponse(finalLength, 1); - - // Flags. These are the complete set of flags we support. - addULong(flags); - - // Domain length (two times). - addUShort(domainBytesLength); - addUShort(domainBytesLength); - - // Domain offset. - addULong(hostBytesLength + 32 + 8); - - // Host length (two times). - addUShort(hostBytesLength); - addUShort(hostBytesLength); - - // Host offset (always 32 + 8). - addULong(32 + 8); - - // Version - addUShort(0x0105); - // Build - addULong(2600); - // NTLM revision - addUShort(0x0f00); - - // Host (workstation) String. - if (hostBytes != null) { - addBytes(hostBytes); - } - // Domain String. - if (domainBytes != null) { - addBytes(domainBytes); - } - } - - } - - /** Type 2 message class */ - static class Type2Message extends NTLMMessage { - protected final byte[] challenge; - protected String target; - protected byte[] targetInfo; - protected final int flags; - - Type2Message(final String messageBody) throws NTLMEngineException { - this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET))); - } - - Type2Message(final byte[] message) throws NTLMEngineException { - super(message, 2); - - // Type 2 message is laid out as follows: - // First 8 bytes: NTLMSSP[0] - // Next 4 bytes: Ulong, value 2 - // Next 8 bytes, starting at offset 12: target field (2 ushort lengths, 1 ulong offset) - // Next 4 bytes, starting at offset 20: Flags, e.g. 0x22890235 - // Next 8 bytes, starting at offset 24: Challenge - // Next 8 bytes, starting at offset 32: ??? (8 bytes of zeros) - // Next 8 bytes, starting at offset 40: targetinfo field (2 ushort lengths, 1 ulong offset) - // Next 2 bytes, major/minor version number (e.g. 0x05 0x02) - // Next 8 bytes, build number - // Next 2 bytes, protocol version number (e.g. 0x00 0x0f) - // Next, various text fields, and a ushort of value 0 at the end - - // Parse out the rest of the info we need from the message - // The nonce is the 8 bytes starting from the byte in position 24. - challenge = new byte[8]; - readBytes(challenge, 24); - - flags = readULong(20); - - // Do the target! - target = null; - // The TARGET_DESIRED flag is said to not have understood semantics - // in Type2 messages, so use the length of the packet to decide - // how to proceed instead - if (getMessageLength() >= 12 + 8) { - final byte[] bytes = readSecurityBuffer(12); - if (bytes.length != 0) { - target = new String(bytes, getCharset(flags)); - } - } - - // Do the target info! - targetInfo = null; - // TARGET_DESIRED flag cannot be relied on, so use packet length - if (getMessageLength() >= 40 + 8) { - final byte[] bytes = readSecurityBuffer(40); - if (bytes.length != 0) { - targetInfo = bytes; - } - } - } - - /** Retrieve the challenge */ - byte[] getChallenge() { - return challenge; - } - - /** Retrieve the target */ - String getTarget() { - return target; - } - - /** Retrieve the target info */ - byte[] getTargetInfo() { - return targetInfo; - } - - /** Retrieve the response flags */ - int getFlags() { - return flags; - } - - } - - /** Type 3 message assembly class */ - static class Type3Message extends NTLMMessage { - // For mic computation - protected final byte[] type1Message; - protected final byte[] type2Message; - // Response flags from the type2 message - protected final int type2Flags; - - protected final byte[] domainBytes; - protected final byte[] hostBytes; - protected final byte[] userBytes; - - protected byte[] lmResp; - protected byte[] ntResp; - protected final byte[] sessionKey; - protected final byte[] exportedSessionKey; - - protected final boolean computeMic; - - /** More primitive constructor: don't include cert or previous messages. - */ - Type3Message(final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation) - throws NTLMEngineException { - this(domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); - } - - /** More primitive constructor: don't include cert or previous messages. - */ - Type3Message(final Random random, final long currentTime, - final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation) - throws NTLMEngineException { - this(random, currentTime, domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); - } - - /** Constructor. Pass the arguments we will need */ - Type3Message(final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation, - final Certificate peerServerCertificate, - final byte[] type1Message, - final byte[] type2Message) - throws NTLMEngineException { - this(RND_GEN, System.currentTimeMillis(), domain, host, user, password, nonce, type2Flags, target, targetInformation, peerServerCertificate, type1Message, type2Message); - } - - /** Constructor. Pass the arguments we will need */ - Type3Message(final Random random, final long currentTime, - final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation, - final Certificate peerServerCertificate, - final byte[] type1Message, - final byte[] type2Message) - throws NTLMEngineException { - - if (random == null) { - throw new NTLMEngineException("Random generator not available"); - } - - // Save the flags - this.type2Flags = type2Flags; - this.type1Message = type1Message; - this.type2Message = type2Message; - - // Strip off domain name from the host! - final String unqualifiedHost = convertHost(host); - // Use only the base domain name! - final String unqualifiedDomain = convertDomain(domain); - - byte[] responseTargetInformation = targetInformation; - if (peerServerCertificate != null) { - responseTargetInformation = addGssMicAvsToTargetInfo(targetInformation, peerServerCertificate); - computeMic = true; - } else { - computeMic = false; - } - - // Create a cipher generator class. Use domain BEFORE it gets modified! - final CipherGen gen = new CipherGen(random, currentTime, - unqualifiedDomain, - user, - password, - nonce, - target, - responseTargetInformation); - - // Use the new code to calculate the responses, including v2 if that - // seems warranted. - byte[] userSessionKey; - try { - // This conditional may not work on Windows Server 2008 R2 and above, where it has not yet - // been tested - if (((type2Flags & FLAG_TARGETINFO_PRESENT) != 0) && - targetInformation != null && target != null) { - // NTLMv2 - ntResp = gen.getNTLMv2Response(); - lmResp = gen.getLMv2Response(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getNTLMv2UserSessionKey(); - } - } else { - // NTLMv1 - if ((type2Flags & FLAG_REQUEST_NTLM2_SESSION) != 0) { - // NTLM2 session stuff is requested - ntResp = gen.getNTLM2SessionResponse(); - lmResp = gen.getLM2SessionResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getNTLM2SessionResponseUserSessionKey(); - } - } else { - ntResp = gen.getNTLMResponse(); - lmResp = gen.getLMResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getNTLMUserSessionKey(); - } - } - } - } catch (final NTLMEngineException e) { - // This likely means we couldn't find the MD4 hash algorithm - - // fail back to just using LM - ntResp = new byte[0]; - lmResp = gen.getLMResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getLMUserSessionKey(); - } - } - - if ((type2Flags & FLAG_REQUEST_SIGN) != 0) { - if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) { - exportedSessionKey = gen.getSecondaryKey(); - sessionKey = RC4(exportedSessionKey, userSessionKey); - } else { - sessionKey = userSessionKey; - exportedSessionKey = sessionKey; - } - } else { - if (computeMic) { - throw new NTLMEngineException("Cannot sign/seal: no exported session key"); - } - sessionKey = null; - exportedSessionKey = null; - } - final Charset charset = getCharset(type2Flags); - hostBytes = unqualifiedHost != null ? unqualifiedHost.getBytes(charset) : null; - domainBytes = unqualifiedDomain != null ? unqualifiedDomain - .toUpperCase(Locale.ROOT).getBytes(charset) : null; - userBytes = user.getBytes(charset); - } - - public byte[] getEncryptedRandomSessionKey() { - return sessionKey; - } - - public byte[] getExportedSessionKey() { - return exportedSessionKey; - } - - /** Assemble the response */ - @Override - protected void buildMessage() { - final int ntRespLen = ntResp.length; - final int lmRespLen = lmResp.length; - - final int domainLen = domainBytes != null ? domainBytes.length : 0; - final int hostLen = hostBytes != null ? hostBytes.length: 0; - final int userLen = userBytes.length; - final int sessionKeyLen; - if (sessionKey != null) { - sessionKeyLen = sessionKey.length; - } else { - sessionKeyLen = 0; - } - - // Calculate the layout within the packet - final int lmRespOffset = 72 + // allocate space for the version - ( computeMic ? 16 : 0 ); // and MIC - final int ntRespOffset = lmRespOffset + lmRespLen; - final int domainOffset = ntRespOffset + ntRespLen; - final int userOffset = domainOffset + domainLen; - final int hostOffset = userOffset + userLen; - final int sessionKeyOffset = hostOffset + hostLen; - final int finalLength = sessionKeyOffset + sessionKeyLen; - - // Start the response. Length includes signature and type - prepareResponse(finalLength, 3); - - // LM Resp Length (twice) - addUShort(lmRespLen); - addUShort(lmRespLen); - - // LM Resp Offset - addULong(lmRespOffset); - - // NT Resp Length (twice) - addUShort(ntRespLen); - addUShort(ntRespLen); - - // NT Resp Offset - addULong(ntRespOffset); - - // Domain length (twice) - addUShort(domainLen); - addUShort(domainLen); - - // Domain offset. - addULong(domainOffset); - - // User Length (twice) - addUShort(userLen); - addUShort(userLen); - - // User offset - addULong(userOffset); - - // Host length (twice) - addUShort(hostLen); - addUShort(hostLen); - - // Host offset - addULong(hostOffset); - - // Session key length (twice) - addUShort(sessionKeyLen); - addUShort(sessionKeyLen); - - // Session key offset - addULong(sessionKeyOffset); - - // Flags. - addULong( - /* - //FLAG_WORKSTATION_PRESENT | - //FLAG_DOMAIN_PRESENT | - - // Required flags - (type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) | - (type2Flags & FLAG_REQUEST_NTLMv1) | - (type2Flags & FLAG_REQUEST_NTLM2_SESSION) | - - // Protocol version request - FLAG_REQUEST_VERSION | - - // Recommended privacy settings - (type2Flags & FLAG_REQUEST_ALWAYS_SIGN) | - (type2Flags & FLAG_REQUEST_SEAL) | - (type2Flags & FLAG_REQUEST_SIGN) | - - // These must be set according to documentation, based on use of SEAL above - (type2Flags & FLAG_REQUEST_128BIT_KEY_EXCH) | - (type2Flags & FLAG_REQUEST_56BIT_ENCRYPTION) | - (type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) | - - (type2Flags & FLAG_TARGETINFO_PRESENT) | - (type2Flags & FLAG_REQUEST_UNICODE_ENCODING) | - (type2Flags & FLAG_REQUEST_TARGET) - */ - type2Flags - ); - - // Version - addUShort(0x0105); - // Build - addULong(2600); - // NTLM revision - addUShort(0x0f00); - - int micPosition = -1; - if ( computeMic ) { - micPosition = currentOutputPosition; - currentOutputPosition += 16; - } - - // Add the actual data - addBytes(lmResp); - addBytes(ntResp); - addBytes(domainBytes); - addBytes(userBytes); - addBytes(hostBytes); - if (sessionKey != null) { - addBytes(sessionKey); - } - - // Write the mic back into its slot in the message - - if (computeMic) { - // Computation of message integrity code (MIC) as specified in [MS-NLMP] section 3.2.5.1.2. - final HMACMD5 hmacMD5 = new HMACMD5( exportedSessionKey ); - hmacMD5.update( type1Message ); - hmacMD5.update( type2Message ); - hmacMD5.update( messageContents ); - final byte[] mic = hmacMD5.getOutput(); - System.arraycopy( mic, 0, messageContents, micPosition, mic.length ); - } - } - - /** - * Add GSS channel binding hash and MIC flag to the targetInfo. - * Looks like this is needed if we want to use exported session key for GSS wrapping. - */ - private byte[] addGssMicAvsToTargetInfo( final byte[] originalTargetInfo, - final Certificate peerServerCertificate ) throws NTLMEngineException - { - final byte[] newTargetInfo = new byte[originalTargetInfo.length + 8 + 20]; - final int appendLength = originalTargetInfo.length - 4; // last tag is MSV_AV_EOL, do not copy that - System.arraycopy( originalTargetInfo, 0, newTargetInfo, 0, appendLength ); - writeUShort( newTargetInfo, MSV_AV_FLAGS, appendLength ); - writeUShort( newTargetInfo, 4, appendLength + 2 ); - writeULong( newTargetInfo, MSV_AV_FLAGS_MIC, appendLength + 4 ); - writeUShort( newTargetInfo, MSV_AV_CHANNEL_BINDINGS, appendLength + 8 ); - writeUShort( newTargetInfo, 16, appendLength + 10 ); - - final byte[] channelBindingsHash; - try - { - final byte[] certBytes = peerServerCertificate.getEncoded(); - final MessageDigest sha256 = MessageDigest.getInstance( "SHA-256" ); - final byte[] certHashBytes = sha256.digest( certBytes ); - final byte[] channelBindingStruct = new byte[16 + 4 + MAGIC_TLS_SERVER_ENDPOINT.length - + certHashBytes.length]; - writeULong( channelBindingStruct, 0x00000035, 16 ); - System.arraycopy( MAGIC_TLS_SERVER_ENDPOINT, 0, channelBindingStruct, 20, - MAGIC_TLS_SERVER_ENDPOINT.length ); - System.arraycopy( certHashBytes, 0, channelBindingStruct, 20 + MAGIC_TLS_SERVER_ENDPOINT.length, - certHashBytes.length ); - final MessageDigest md5 = getMD5(); - channelBindingsHash = md5.digest( channelBindingStruct ); - } - catch ( final CertificateEncodingException e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - catch ( final NoSuchAlgorithmException e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - - System.arraycopy( channelBindingsHash, 0, newTargetInfo, appendLength + 12, 16 ); - return newTargetInfo; - } - - } - - static void writeUShort(final byte[] buffer, final int value, final int offset) { - buffer[offset] = ( byte ) ( value & 0xff ); - buffer[offset + 1] = ( byte ) ( value >> 8 & 0xff ); - } - - static void writeULong(final byte[] buffer, final int value, final int offset) { - buffer[offset] = (byte) (value & 0xff); - buffer[offset + 1] = (byte) (value >> 8 & 0xff); - buffer[offset + 2] = (byte) (value >> 16 & 0xff); - buffer[offset + 3] = (byte) (value >> 24 & 0xff); - } - - static int F(final int x, final int y, final int z) { - return ((x & y) | (~x & z)); - } - - static int G(final int x, final int y, final int z) { - return ((x & y) | (x & z) | (y & z)); - } - - static int H(final int x, final int y, final int z) { - return (x ^ y ^ z); - } - - static int rotintlft(final int val, final int numbits) { - return ((val << numbits) | (val >>> (32 - numbits))); - } - - static MessageDigest getMD5() { - try { - return MessageDigest.getInstance("MD5"); - } catch (final NoSuchAlgorithmException ex) { - throw new RuntimeException("MD5 message digest doesn't seem to exist - fatal error: "+ex.getMessage(), ex); - } - } - - /** - * Cryptography support - MD4. The following class was based loosely on the - * RFC and on code found at http://www.cs.umd.edu/~harry/jotp/src/md.java. - * Code correctness was verified by looking at MD4.java from the jcifs - * library (http://jcifs.samba.org). It was massaged extensively to the - * final form found here by Karl Wright (kwright@metacarta.com). - */ - static class MD4 { - protected int A = 0x67452301; - protected int B = 0xefcdab89; - protected int C = 0x98badcfe; - protected int D = 0x10325476; - protected long count = 0L; - protected final byte[] dataBuffer = new byte[64]; - - MD4() { - } - - void update(final byte[] input) { - // We always deal with 512 bits at a time. Correspondingly, there is - // a buffer 64 bytes long that we write data into until it gets - // full. - int curBufferPos = (int) (count & 63L); - int inputIndex = 0; - while (input.length - inputIndex + curBufferPos >= dataBuffer.length) { - // We have enough data to do the next step. Do a partial copy - // and a transform, updating inputIndex and curBufferPos - // accordingly - final int transferAmt = dataBuffer.length - curBufferPos; - System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); - count += transferAmt; - curBufferPos = 0; - inputIndex += transferAmt; - processBuffer(); - } - - // If there's anything left, copy it into the buffer and leave it. - // We know there's not enough left to process. - if (inputIndex < input.length) { - final int transferAmt = input.length - inputIndex; - System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); - count += transferAmt; - curBufferPos += transferAmt; - } - } - - byte[] getOutput() { - // Feed pad/length data into engine. This must round out the input - // to a multiple of 512 bits. - final int bufferIndex = (int) (count & 63L); - final int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); - final byte[] postBytes = new byte[padLen + 8]; - // Leading 0x80, specified amount of zero padding, then length in - // bits. - postBytes[0] = (byte) 0x80; - // Fill out the last 8 bytes with the length - for (int i = 0; i < 8; i++) { - postBytes[padLen + i] = (byte) ((count * 8) >>> (8 * i)); - } - - // Update the engine - update(postBytes); - - // Calculate final result - final byte[] result = new byte[16]; - writeULong(result, A, 0); - writeULong(result, B, 4); - writeULong(result, C, 8); - writeULong(result, D, 12); - return result; - } - - protected void processBuffer() { - // Convert current buffer to 16 ulongs - final int[] d = new int[16]; - - for (int i = 0; i < 16; i++) { - d[i] = (dataBuffer[i * 4] & 0xff) + ((dataBuffer[i * 4 + 1] & 0xff) << 8) - + ((dataBuffer[i * 4 + 2] & 0xff) << 16) - + ((dataBuffer[i * 4 + 3] & 0xff) << 24); - } - - // Do a round of processing - final int AA = A; - final int BB = B; - final int CC = C; - final int DD = D; - round1(d); - round2(d); - round3(d); - A += AA; - B += BB; - C += CC; - D += DD; - - } - - protected void round1(final int[] d) { - A = rotintlft((A + F(B, C, D) + d[0]), 3); - D = rotintlft((D + F(A, B, C) + d[1]), 7); - C = rotintlft((C + F(D, A, B) + d[2]), 11); - B = rotintlft((B + F(C, D, A) + d[3]), 19); - - A = rotintlft((A + F(B, C, D) + d[4]), 3); - D = rotintlft((D + F(A, B, C) + d[5]), 7); - C = rotintlft((C + F(D, A, B) + d[6]), 11); - B = rotintlft((B + F(C, D, A) + d[7]), 19); - - A = rotintlft((A + F(B, C, D) + d[8]), 3); - D = rotintlft((D + F(A, B, C) + d[9]), 7); - C = rotintlft((C + F(D, A, B) + d[10]), 11); - B = rotintlft((B + F(C, D, A) + d[11]), 19); - - A = rotintlft((A + F(B, C, D) + d[12]), 3); - D = rotintlft((D + F(A, B, C) + d[13]), 7); - C = rotintlft((C + F(D, A, B) + d[14]), 11); - B = rotintlft((B + F(C, D, A) + d[15]), 19); - } - - protected void round2(final int[] d) { - A = rotintlft((A + G(B, C, D) + d[0] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[4] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[8] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[12] + 0x5a827999), 13); - - A = rotintlft((A + G(B, C, D) + d[1] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[5] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[9] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[13] + 0x5a827999), 13); - - A = rotintlft((A + G(B, C, D) + d[2] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[6] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[10] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[14] + 0x5a827999), 13); - - A = rotintlft((A + G(B, C, D) + d[3] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[7] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[11] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[15] + 0x5a827999), 13); - - } - - protected void round3(final int[] d) { - A = rotintlft((A + H(B, C, D) + d[0] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[8] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[4] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[12] + 0x6ed9eba1), 15); - - A = rotintlft((A + H(B, C, D) + d[2] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[10] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[6] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[14] + 0x6ed9eba1), 15); - - A = rotintlft((A + H(B, C, D) + d[1] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[9] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[5] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[13] + 0x6ed9eba1), 15); - - A = rotintlft((A + H(B, C, D) + d[3] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[11] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[7] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[15] + 0x6ed9eba1), 15); - - } - - } - - /** - * Cryptography support - HMACMD5 - algorithmically based on various web - * resources by Karl Wright - */ - static class HMACMD5 { - protected final byte[] ipad; - protected final byte[] opad; - protected final MessageDigest md5; - - HMACMD5(final byte[] input) { - byte[] key = input; - md5 = getMD5(); - - // Initialize the pad buffers with the key - ipad = new byte[64]; - opad = new byte[64]; - - int keyLength = key.length; - if (keyLength > 64) { - // Use MD5 of the key instead, as described in RFC 2104 - md5.update(key); - key = md5.digest(); - keyLength = key.length; - } - int i = 0; - while (i < keyLength) { - ipad[i] = (byte) (key[i] ^ (byte) 0x36); - opad[i] = (byte) (key[i] ^ (byte) 0x5c); - i++; - } - while (i < 64) { - ipad[i] = (byte) 0x36; - opad[i] = (byte) 0x5c; - i++; - } - - // Very important: processChallenge the digest with the ipad buffer - md5.reset(); - md5.update(ipad); - - } - - /** Grab the current digest. This is the "answer". */ - byte[] getOutput() { - final byte[] digest = md5.digest(); - md5.update(opad); - return md5.digest(digest); - } - - /** Update by adding a complete array */ - void update(final byte[] input) { - md5.update(input); - } - - /** Update the algorithm */ - void update(final byte[] input, final int offset, final int length) { - md5.update(input, offset, length); - } - - } - - @Override - public String generateType1Msg( - final String domain, - final String workstation) throws NTLMEngineException { - return getType1Message(workstation, domain); - } - - @Override - public String generateType3Msg( - final String username, - final String password, - final String domain, - final String workstation, - final String challenge) throws NTLMEngineException { - final Type2Message t2m = new Type2Message(challenge); - return getType3Message( - username, - password, - workstation, - domain, - t2m.getChallenge(), - t2m.getFlags(), - t2m.getTarget(), - t2m.getTargetInfo()); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.auth; + +import java.nio.charset.Charset; +import org.apache.http.Consts; +import java.security.Key; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Locale; +import java.util.Random; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.Certificate; + +import org.apache.commons.codec.binary.Base64; + +/** + * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM + * authentication protocol. + * + * @since 4.1 + */ +final class NTLMEngineImpl implements NTLMEngine { + + /** Unicode encoding */ + private static final Charset UNICODE_LITTLE_UNMARKED = Charset.forName("UnicodeLittleUnmarked"); + /** Character encoding */ + private static final Charset DEFAULT_CHARSET = Consts.ASCII; + + // Flags we use; descriptions according to: + // http://davenport.sourceforge.net/ntlm.html + // and + // http://msdn.microsoft.com/en-us/library/cc236650%28v=prot.20%29.aspx + // [MS-NLMP] section 2.2.2.5 + static final int FLAG_REQUEST_UNICODE_ENCODING = 0x00000001; // Unicode string encoding requested + static final int FLAG_REQUEST_OEM_ENCODING = 0x00000002; // OEM string encoding requested + static final int FLAG_REQUEST_TARGET = 0x00000004; // Requests target field + static final int FLAG_REQUEST_SIGN = 0x00000010; // Requests all messages have a signature attached, in NEGOTIATE message. + static final int FLAG_REQUEST_SEAL = 0x00000020; // Request key exchange for message confidentiality in NEGOTIATE message. MUST be used in conjunction with 56BIT. + static final int FLAG_REQUEST_LAN_MANAGER_KEY = 0x00000080; // Request Lan Manager key instead of user session key + static final int FLAG_REQUEST_NTLMv1 = 0x00000200; // Request NTLMv1 security. MUST be set in NEGOTIATE and CHALLENGE both + static final int FLAG_DOMAIN_PRESENT = 0x00001000; // Domain is present in message + static final int FLAG_WORKSTATION_PRESENT = 0x00002000; // Workstation is present in message + static final int FLAG_REQUEST_ALWAYS_SIGN = 0x00008000; // Requests a signature block on all messages. Overridden by REQUEST_SIGN and REQUEST_SEAL. + static final int FLAG_REQUEST_NTLM2_SESSION = 0x00080000; // From server in challenge, requesting NTLM2 session security + static final int FLAG_REQUEST_VERSION = 0x02000000; // Request protocol version + static final int FLAG_TARGETINFO_PRESENT = 0x00800000; // From server in challenge message, indicating targetinfo is present + static final int FLAG_REQUEST_128BIT_KEY_EXCH = 0x20000000; // Request explicit 128-bit key exchange + static final int FLAG_REQUEST_EXPLICIT_KEY_EXCH = 0x40000000; // Request explicit key exchange + static final int FLAG_REQUEST_56BIT_ENCRYPTION = 0x80000000; // Must be used in conjunction with SEAL + + // Attribute-value identifiers (AvId) + // according to [MS-NLMP] section 2.2.2.1 + static final int MSV_AV_EOL = 0x0000; // Indicates that this is the last AV_PAIR in the list. + static final int MSV_AV_NB_COMPUTER_NAME = 0x0001; // The server's NetBIOS computer name. + static final int MSV_AV_NB_DOMAIN_NAME = 0x0002; // The server's NetBIOS domain name. + static final int MSV_AV_DNS_COMPUTER_NAME = 0x0003; // The fully qualified domain name (FQDN) of the computer. + static final int MSV_AV_DNS_DOMAIN_NAME = 0x0004; // The FQDN of the domain. + static final int MSV_AV_DNS_TREE_NAME = 0x0005; // The FQDN of the forest. + static final int MSV_AV_FLAGS = 0x0006; // A 32-bit value indicating server or client configuration. + static final int MSV_AV_TIMESTAMP = 0x0007; // server local time + static final int MSV_AV_SINGLE_HOST = 0x0008; // A Single_Host_Data structure. + static final int MSV_AV_TARGET_NAME = 0x0009; // The SPN of the target server. + static final int MSV_AV_CHANNEL_BINDINGS = 0x000A; // A channel bindings hash. + + static final int MSV_AV_FLAGS_ACCOUNT_AUTH_CONSTAINED = 0x00000001; // Indicates to the client that the account authentication is constrained. + static final int MSV_AV_FLAGS_MIC = 0x00000002; // Indicates that the client is providing message integrity in the MIC field in the AUTHENTICATE_MESSAGE. + static final int MSV_AV_FLAGS_UNTRUSTED_TARGET_SPN = 0x00000004; // Indicates that the client is providing a target SPN generated from an untrusted source. + + /** Secure random generator */ + private static final java.security.SecureRandom RND_GEN; + static { + java.security.SecureRandom rnd = null; + try { + rnd = java.security.SecureRandom.getInstance("SHA1PRNG"); + } catch (final Exception ignore) { + } + RND_GEN = rnd; + } + + /** The signature string as bytes in the default encoding */ + private static final byte[] SIGNATURE = getNullTerminatedAsciiString("NTLMSSP"); + + // Key derivation magic strings for the SIGNKEY algorithm defined in + // [MS-NLMP] section 3.4.5.2 + private static final byte[] SIGN_MAGIC_SERVER = getNullTerminatedAsciiString( + "session key to server-to-client signing key magic constant"); + private static final byte[] SIGN_MAGIC_CLIENT = getNullTerminatedAsciiString( + "session key to client-to-server signing key magic constant"); + private static final byte[] SEAL_MAGIC_SERVER = getNullTerminatedAsciiString( + "session key to server-to-client sealing key magic constant"); + private static final byte[] SEAL_MAGIC_CLIENT = getNullTerminatedAsciiString( + "session key to client-to-server sealing key magic constant"); + + // prefix for GSS API channel binding + private static final byte[] MAGIC_TLS_SERVER_ENDPOINT = "tls-server-end-point:".getBytes(Consts.ASCII); + + private static byte[] getNullTerminatedAsciiString( final String source ) + { + final byte[] bytesWithoutNull = source.getBytes(Consts.ASCII); + final byte[] target = new byte[bytesWithoutNull.length + 1]; + System.arraycopy(bytesWithoutNull, 0, target, 0, bytesWithoutNull.length); + target[bytesWithoutNull.length] = (byte) 0x00; + return target; + } + + private static final String TYPE_1_MESSAGE = new Type1Message().getResponse(); + + NTLMEngineImpl() { + } + + /** + * Creates the first message (type 1 message) in the NTLM authentication + * sequence. This message includes the user name, domain and host for the + * authentication session. + * + * @param host + * the computer name of the host requesting authentication. + * @param domain + * The domain to authenticate with. + * @return String the message to add to the HTTP request header. + */ + static String getType1Message(final String host, final String domain) { + // For compatibility reason do not include domain and host in type 1 message + //return new Type1Message(domain, host).getResponse(); + return TYPE_1_MESSAGE; + } + + /** + * Creates the type 3 message using the given server nonce. The type 3 + * message includes all the information for authentication, host, domain, + * username and the result of encrypting the nonce sent by the server using + * the user's password as the key. + * + * @param user + * The user name. This should not include the domain name. + * @param password + * The password. + * @param host + * The host that is originating the authentication request. + * @param domain + * The domain to authenticate within. + * @param nonce + * the 8 byte array the server sent. + * @return The type 3 message. + * @throws NTLMEngineException + * If {@encrypt(byte[],byte[])} fails. + */ + static String getType3Message(final String user, final String password, final String host, final String domain, + final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation) + throws NTLMEngineException { + return new Type3Message(domain, host, user, password, nonce, type2Flags, target, + targetInformation).getResponse(); + } + + /** + * Creates the type 3 message using the given server nonce. The type 3 + * message includes all the information for authentication, host, domain, + * username and the result of encrypting the nonce sent by the server using + * the user's password as the key. + * + * @param user + * The user name. This should not include the domain name. + * @param password + * The password. + * @param host + * The host that is originating the authentication request. + * @param domain + * The domain to authenticate within. + * @param nonce + * the 8 byte array the server sent. + * @return The type 3 message. + * @throws NTLMEngineException + * If {@encrypt(byte[],byte[])} fails. + */ + static String getType3Message(final String user, final String password, final String host, final String domain, + final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation, + final Certificate peerServerCertificate, final byte[] type1Message, final byte[] type2Message) + throws NTLMEngineException { + return new Type3Message(domain, host, user, password, nonce, type2Flags, target, + targetInformation, peerServerCertificate, type1Message, type2Message).getResponse(); + } + + private static int readULong(final byte[] src, final int index) throws NTLMEngineException { + if (src.length < index + 4) { + return 0; + } + return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) + | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); + } + + private static int readUShort(final byte[] src, final int index) throws NTLMEngineException { + if (src.length < index + 2) { + return 0; + } + return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); + } + + private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException { + final int length = readUShort(src, index); + final int offset = readULong(src, index + 4); + if (src.length < offset + length) { + return new byte[length]; + } + final byte[] buffer = new byte[length]; + System.arraycopy(src, offset, buffer, 0, length); + return buffer; + } + + /** Calculate a challenge block */ + private static byte[] makeRandomChallenge(final Random random) throws NTLMEngineException { + final byte[] rval = new byte[8]; + synchronized (random) { + random.nextBytes(rval); + } + return rval; + } + + /** Calculate a 16-byte secondary key */ + private static byte[] makeSecondaryKey(final Random random) throws NTLMEngineException { + final byte[] rval = new byte[16]; + synchronized (random) { + random.nextBytes(rval); + } + return rval; + } + + protected static class CipherGen { + + protected final Random random; + protected final long currentTime; + + protected final String domain; + protected final String user; + protected final String password; + protected final byte[] challenge; + protected final String target; + protected final byte[] targetInformation; + + // Information we can generate but may be passed in (for testing) + protected byte[] clientChallenge; + protected byte[] clientChallenge2; + protected byte[] secondaryKey; + protected byte[] timestamp; + + // Stuff we always generate + protected byte[] lmHash = null; + protected byte[] lmResponse = null; + protected byte[] ntlmHash = null; + protected byte[] ntlmResponse = null; + protected byte[] ntlmv2Hash = null; + protected byte[] lmv2Hash = null; + protected byte[] lmv2Response = null; + protected byte[] ntlmv2Blob = null; + protected byte[] ntlmv2Response = null; + protected byte[] ntlm2SessionResponse = null; + protected byte[] lm2SessionResponse = null; + protected byte[] lmUserSessionKey = null; + protected byte[] ntlmUserSessionKey = null; + protected byte[] ntlmv2UserSessionKey = null; + protected byte[] ntlm2SessionResponseUserSessionKey = null; + protected byte[] lanManagerSessionKey = null; + + @Deprecated + public CipherGen(final String domain, final String user, final String password, + final byte[] challenge, final String target, final byte[] targetInformation, + final byte[] clientChallenge, final byte[] clientChallenge2, + final byte[] secondaryKey, final byte[] timestamp) { + this(RND_GEN, System.currentTimeMillis(), + domain, user, password, challenge, target, targetInformation, + clientChallenge, clientChallenge2, + secondaryKey, timestamp); + } + + public CipherGen(final Random random, final long currentTime, + final String domain, final String user, final String password, + final byte[] challenge, final String target, final byte[] targetInformation, + final byte[] clientChallenge, final byte[] clientChallenge2, + final byte[] secondaryKey, final byte[] timestamp) { + this.random = random; + this.currentTime = currentTime; + + this.domain = domain; + this.target = target; + this.user = user; + this.password = password; + this.challenge = challenge; + this.targetInformation = targetInformation; + this.clientChallenge = clientChallenge; + this.clientChallenge2 = clientChallenge2; + this.secondaryKey = secondaryKey; + this.timestamp = timestamp; + } + + @Deprecated + public CipherGen(final String domain, + final String user, + final String password, + final byte[] challenge, + final String target, + final byte[] targetInformation) { + this(RND_GEN, System.currentTimeMillis(), domain, user, password, challenge, target, targetInformation); + } + + public CipherGen(final Random random, final long currentTime, + final String domain, + final String user, + final String password, + final byte[] challenge, + final String target, + final byte[] targetInformation) { + this(random, currentTime, domain, user, password, challenge, target, targetInformation, null, null, null, null); + } + + /** Calculate and return client challenge */ + public byte[] getClientChallenge() + throws NTLMEngineException { + if (clientChallenge == null) { + clientChallenge = makeRandomChallenge(random); + } + return clientChallenge; + } + + /** Calculate and return second client challenge */ + public byte[] getClientChallenge2() + throws NTLMEngineException { + if (clientChallenge2 == null) { + clientChallenge2 = makeRandomChallenge(random); + } + return clientChallenge2; + } + + /** Calculate and return random secondary key */ + public byte[] getSecondaryKey() + throws NTLMEngineException { + if (secondaryKey == null) { + secondaryKey = makeSecondaryKey(random); + } + return secondaryKey; + } + + /** Calculate and return the LMHash */ + public byte[] getLMHash() + throws NTLMEngineException { + if (lmHash == null) { + lmHash = lmHash(password); + } + return lmHash; + } + + /** Calculate and return the LMResponse */ + public byte[] getLMResponse() + throws NTLMEngineException { + if (lmResponse == null) { + lmResponse = lmResponse(getLMHash(),challenge); + } + return lmResponse; + } + + /** Calculate and return the NTLMHash */ + public byte[] getNTLMHash() + throws NTLMEngineException { + if (ntlmHash == null) { + ntlmHash = ntlmHash(password); + } + return ntlmHash; + } + + /** Calculate and return the NTLMResponse */ + public byte[] getNTLMResponse() + throws NTLMEngineException { + if (ntlmResponse == null) { + ntlmResponse = lmResponse(getNTLMHash(),challenge); + } + return ntlmResponse; + } + + /** Calculate the LMv2 hash */ + public byte[] getLMv2Hash() + throws NTLMEngineException { + if (lmv2Hash == null) { + lmv2Hash = lmv2Hash(domain, user, getNTLMHash()); + } + return lmv2Hash; + } + + /** Calculate the NTLMv2 hash */ + public byte[] getNTLMv2Hash() + throws NTLMEngineException { + if (ntlmv2Hash == null) { + ntlmv2Hash = ntlmv2Hash(domain, user, getNTLMHash()); + } + return ntlmv2Hash; + } + + /** Calculate a timestamp */ + public byte[] getTimestamp() { + if (timestamp == null) { + long time = this.currentTime; + time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch. + time *= 10000; // tenths of a microsecond. + // convert to little-endian byte array. + timestamp = new byte[8]; + for (int i = 0; i < 8; i++) { + timestamp[i] = (byte) time; + time >>>= 8; + } + } + return timestamp; + } + + /** Calculate the NTLMv2Blob */ + public byte[] getNTLMv2Blob() + throws NTLMEngineException { + if (ntlmv2Blob == null) { + ntlmv2Blob = createBlob(getClientChallenge2(), targetInformation, getTimestamp()); + } + return ntlmv2Blob; + } + + /** Calculate the NTLMv2Response */ + public byte[] getNTLMv2Response() + throws NTLMEngineException { + if (ntlmv2Response == null) { + ntlmv2Response = lmv2Response(getNTLMv2Hash(),challenge,getNTLMv2Blob()); + } + return ntlmv2Response; + } + + /** Calculate the LMv2Response */ + public byte[] getLMv2Response() + throws NTLMEngineException { + if (lmv2Response == null) { + lmv2Response = lmv2Response(getLMv2Hash(),challenge,getClientChallenge()); + } + return lmv2Response; + } + + /** Get NTLM2SessionResponse */ + public byte[] getNTLM2SessionResponse() + throws NTLMEngineException { + if (ntlm2SessionResponse == null) { + ntlm2SessionResponse = ntlm2SessionResponse(getNTLMHash(),challenge,getClientChallenge()); + } + return ntlm2SessionResponse; + } + + /** Calculate and return LM2 session response */ + public byte[] getLM2SessionResponse() + throws NTLMEngineException { + if (lm2SessionResponse == null) { + final byte[] clntChallenge = getClientChallenge(); + lm2SessionResponse = new byte[24]; + System.arraycopy(clntChallenge, 0, lm2SessionResponse, 0, clntChallenge.length); + Arrays.fill(lm2SessionResponse, clntChallenge.length, lm2SessionResponse.length, (byte) 0x00); + } + return lm2SessionResponse; + } + + /** Get LMUserSessionKey */ + public byte[] getLMUserSessionKey() + throws NTLMEngineException { + if (lmUserSessionKey == null) { + lmUserSessionKey = new byte[16]; + System.arraycopy(getLMHash(), 0, lmUserSessionKey, 0, 8); + Arrays.fill(lmUserSessionKey, 8, 16, (byte) 0x00); + } + return lmUserSessionKey; + } + + /** Get NTLMUserSessionKey */ + public byte[] getNTLMUserSessionKey() + throws NTLMEngineException { + if (ntlmUserSessionKey == null) { + final MD4 md4 = new MD4(); + md4.update(getNTLMHash()); + ntlmUserSessionKey = md4.getOutput(); + } + return ntlmUserSessionKey; + } + + /** GetNTLMv2UserSessionKey */ + public byte[] getNTLMv2UserSessionKey() + throws NTLMEngineException { + if (ntlmv2UserSessionKey == null) { + final byte[] ntlmv2hash = getNTLMv2Hash(); + final byte[] truncatedResponse = new byte[16]; + System.arraycopy(getNTLMv2Response(), 0, truncatedResponse, 0, 16); + ntlmv2UserSessionKey = hmacMD5(truncatedResponse, ntlmv2hash); + } + return ntlmv2UserSessionKey; + } + + /** Get NTLM2SessionResponseUserSessionKey */ + public byte[] getNTLM2SessionResponseUserSessionKey() + throws NTLMEngineException { + if (ntlm2SessionResponseUserSessionKey == null) { + final byte[] ntlm2SessionResponseNonce = getLM2SessionResponse(); + final byte[] sessionNonce = new byte[challenge.length + ntlm2SessionResponseNonce.length]; + System.arraycopy(challenge, 0, sessionNonce, 0, challenge.length); + System.arraycopy(ntlm2SessionResponseNonce, 0, sessionNonce, challenge.length, ntlm2SessionResponseNonce.length); + ntlm2SessionResponseUserSessionKey = hmacMD5(sessionNonce,getNTLMUserSessionKey()); + } + return ntlm2SessionResponseUserSessionKey; + } + + /** Get LAN Manager session key */ + public byte[] getLanManagerSessionKey() + throws NTLMEngineException { + if (lanManagerSessionKey == null) { + try { + final byte[] keyBytes = new byte[14]; + System.arraycopy(getLMHash(), 0, keyBytes, 0, 8); + Arrays.fill(keyBytes, 8, keyBytes.length, (byte)0xbd); + final Key lowKey = createDESKey(keyBytes, 0); + final Key highKey = createDESKey(keyBytes, 7); + final byte[] truncatedResponse = new byte[8]; + System.arraycopy(getLMResponse(), 0, truncatedResponse, 0, truncatedResponse.length); + Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, lowKey); + final byte[] lowPart = des.doFinal(truncatedResponse); + des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, highKey); + final byte[] highPart = des.doFinal(truncatedResponse); + lanManagerSessionKey = new byte[16]; + System.arraycopy(lowPart, 0, lanManagerSessionKey, 0, lowPart.length); + System.arraycopy(highPart, 0, lanManagerSessionKey, lowPart.length, highPart.length); + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + return lanManagerSessionKey; + } + } + + /** Calculates HMAC-MD5 */ + static byte[] hmacMD5(final byte[] value, final byte[] key) + throws NTLMEngineException { + final HMACMD5 hmacMD5 = new HMACMD5(key); + hmacMD5.update(value); + return hmacMD5.getOutput(); + } + + /** Calculates RC4 */ + static byte[] RC4(final byte[] value, final byte[] key) + throws NTLMEngineException { + try { + final Cipher rc4 = Cipher.getInstance("RC4"); + rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC4")); + return rc4.doFinal(value); + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Calculates the NTLM2 Session Response for the given challenge, using the + * specified password and client challenge. + * + * @return The NTLM2 Session Response. This is placed in the NTLM response + * field of the Type 3 message; the LM response field contains the + * client challenge, null-padded to 24 bytes. + */ + static byte[] ntlm2SessionResponse(final byte[] ntlmHash, final byte[] challenge, + final byte[] clientChallenge) throws NTLMEngineException { + try { + final MessageDigest md5 = getMD5(); + md5.update(challenge); + md5.update(clientChallenge); + final byte[] digest = md5.digest(); + + final byte[] sessionHash = new byte[8]; + System.arraycopy(digest, 0, sessionHash, 0, 8); + return lmResponse(ntlmHash, sessionHash); + } catch (final Exception e) { + if (e instanceof NTLMEngineException) { + throw (NTLMEngineException) e; + } + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Creates the LM Hash of the user's password. + * + * @param password + * The password. + * + * @return The LM Hash of the given password, used in the calculation of the + * LM Response. + */ + private static byte[] lmHash(final String password) throws NTLMEngineException { + try { + final byte[] oemPassword = password.toUpperCase(Locale.ROOT).getBytes(Consts.ASCII); + final int length = Math.min(oemPassword.length, 14); + final byte[] keyBytes = new byte[14]; + System.arraycopy(oemPassword, 0, keyBytes, 0, length); + final Key lowKey = createDESKey(keyBytes, 0); + final Key highKey = createDESKey(keyBytes, 7); + final byte[] magicConstant = "KGS!@#$%".getBytes(Consts.ASCII); + final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, lowKey); + final byte[] lowHash = des.doFinal(magicConstant); + des.init(Cipher.ENCRYPT_MODE, highKey); + final byte[] highHash = des.doFinal(magicConstant); + final byte[] lmHash = new byte[16]; + System.arraycopy(lowHash, 0, lmHash, 0, 8); + System.arraycopy(highHash, 0, lmHash, 8, 8); + return lmHash; + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Creates the NTLM Hash of the user's password. + * + * @param password + * The password. + * + * @return The NTLM Hash of the given password, used in the calculation of + * the NTLM Response and the NTLMv2 and LMv2 Hashes. + */ + private static byte[] ntlmHash(final String password) throws NTLMEngineException { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException("Unicode not supported"); + } + final byte[] unicodePassword = password.getBytes(UNICODE_LITTLE_UNMARKED); + final MD4 md4 = new MD4(); + md4.update(unicodePassword); + return md4.getOutput(); + } + + /** + * Creates the LMv2 Hash of the user's password. + * + * @return The LMv2 Hash, used in the calculation of the NTLMv2 and LMv2 + * Responses. + */ + private static byte[] lmv2Hash(final String domain, final String user, final byte[] ntlmHash) + throws NTLMEngineException { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException("Unicode not supported"); + } + final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); + // Upper case username, upper case domain! + hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); + if (domain != null) { + hmacMD5.update(domain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); + } + return hmacMD5.getOutput(); + } + + /** + * Creates the NTLMv2 Hash of the user's password. + * + * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 and LMv2 + * Responses. + */ + private static byte[] ntlmv2Hash(final String domain, final String user, final byte[] ntlmHash) + throws NTLMEngineException { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException("Unicode not supported"); + } + final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); + // Upper case username, mixed case target!! + hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); + if (domain != null) { + hmacMD5.update(domain.getBytes(UNICODE_LITTLE_UNMARKED)); + } + return hmacMD5.getOutput(); + } + + /** + * Creates the LM Response from the given hash and Type 2 challenge. + * + * @param hash + * The LM or NTLM Hash. + * @param challenge + * The server challenge from the Type 2 message. + * + * @return The response (either LM or NTLM, depending on the provided hash). + */ + private static byte[] lmResponse(final byte[] hash, final byte[] challenge) throws NTLMEngineException { + try { + final byte[] keyBytes = new byte[21]; + System.arraycopy(hash, 0, keyBytes, 0, 16); + final Key lowKey = createDESKey(keyBytes, 0); + final Key middleKey = createDESKey(keyBytes, 7); + final Key highKey = createDESKey(keyBytes, 14); + final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, lowKey); + final byte[] lowResponse = des.doFinal(challenge); + des.init(Cipher.ENCRYPT_MODE, middleKey); + final byte[] middleResponse = des.doFinal(challenge); + des.init(Cipher.ENCRYPT_MODE, highKey); + final byte[] highResponse = des.doFinal(challenge); + final byte[] lmResponse = new byte[24]; + System.arraycopy(lowResponse, 0, lmResponse, 0, 8); + System.arraycopy(middleResponse, 0, lmResponse, 8, 8); + System.arraycopy(highResponse, 0, lmResponse, 16, 8); + return lmResponse; + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Creates the LMv2 Response from the given hash, client data, and Type 2 + * challenge. + * + * @param hash + * The NTLMv2 Hash. + * @param clientData + * The client data (blob or client challenge). + * @param challenge + * The server challenge from the Type 2 message. + * + * @return The response (either NTLMv2 or LMv2, depending on the client + * data). + */ + private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData) + throws NTLMEngineException { + final HMACMD5 hmacMD5 = new HMACMD5(hash); + hmacMD5.update(challenge); + hmacMD5.update(clientData); + final byte[] mac = hmacMD5.getOutput(); + final byte[] lmv2Response = new byte[mac.length + clientData.length]; + System.arraycopy(mac, 0, lmv2Response, 0, mac.length); + System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length); + return lmv2Response; + } + + static enum Mode + { + CLIENT, SERVER; + } + + static class Handle + { + final private byte[] exportedSessionKey; + private byte[] signingKey; + private byte[] sealingKey; + private final Cipher rc4; + final Mode mode; + final private boolean isConnection; + int sequenceNumber = 0; + + + Handle( final byte[] exportedSessionKey, final Mode mode, final boolean isConnection ) + throws NTLMEngineException + { + this.exportedSessionKey = exportedSessionKey; + this.isConnection = isConnection; + this.mode = mode; + try + { + final MessageDigest signMd5 = getMD5(); + final MessageDigest sealMd5 = getMD5(); + signMd5.update( exportedSessionKey ); + sealMd5.update( exportedSessionKey ); + if ( mode == Mode.CLIENT ) + { + signMd5.update( SIGN_MAGIC_CLIENT ); + sealMd5.update( SEAL_MAGIC_CLIENT ); + } + else + { + signMd5.update( SIGN_MAGIC_SERVER ); + sealMd5.update( SEAL_MAGIC_SERVER ); + } + signingKey = signMd5.digest(); + sealingKey = sealMd5.digest(); + } + catch ( final Exception e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + rc4 = initCipher(); + } + + public byte[] getSigningKey() + { + return signingKey; + } + + + public byte[] getSealingKey() + { + return sealingKey; + } + + private Cipher initCipher() throws NTLMEngineException + { + final Cipher cipher; + try + { + cipher = Cipher.getInstance( "RC4" ); + if ( mode == Mode.CLIENT ) + { + cipher.init( Cipher.ENCRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); + } + else + { + cipher.init( Cipher.DECRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); + } + } + catch ( final Exception e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + return cipher; + } + + + private void advanceMessageSequence() throws NTLMEngineException + { + if ( !isConnection ) + { + final MessageDigest sealMd5 = getMD5(); + sealMd5.update( sealingKey ); + final byte[] seqNumBytes = new byte[4]; + writeULong( seqNumBytes, sequenceNumber, 0 ); + sealMd5.update( seqNumBytes ); + sealingKey = sealMd5.digest(); + initCipher(); + } + sequenceNumber++; + } + + private byte[] encrypt( final byte[] data ) throws NTLMEngineException + { + return rc4.update( data ); + } + + private byte[] decrypt( final byte[] data ) throws NTLMEngineException + { + return rc4.update( data ); + } + + private byte[] computeSignature( final byte[] message ) throws NTLMEngineException + { + final byte[] sig = new byte[16]; + + // version + sig[0] = 0x01; + sig[1] = 0x00; + sig[2] = 0x00; + sig[3] = 0x00; + + // HMAC (first 8 bytes) + final HMACMD5 hmacMD5 = new HMACMD5( signingKey ); + hmacMD5.update( encodeLong( sequenceNumber ) ); + hmacMD5.update( message ); + final byte[] hmac = hmacMD5.getOutput(); + final byte[] trimmedHmac = new byte[8]; + System.arraycopy( hmac, 0, trimmedHmac, 0, 8 ); + final byte[] encryptedHmac = encrypt( trimmedHmac ); + System.arraycopy( encryptedHmac, 0, sig, 4, 8 ); + + // sequence number + encodeLong( sig, 12, sequenceNumber ); + + return sig; + } + + private boolean validateSignature( final byte[] signature, final byte message[] ) throws NTLMEngineException + { + final byte[] computedSignature = computeSignature( message ); + // log.info( "SSSSS validateSignature("+seqNumber+")\n" + // + " received: " + DebugUtil.dump( signature ) + "\n" + // + " computed: " + DebugUtil.dump( computedSignature ) ); + return Arrays.equals( signature, computedSignature ); + } + + public byte[] signAndEncryptMessage( final byte[] cleartextMessage ) throws NTLMEngineException + { + final byte[] encryptedMessage = encrypt( cleartextMessage ); + final byte[] signature = computeSignature( cleartextMessage ); + final byte[] outMessage = new byte[signature.length + encryptedMessage.length]; + System.arraycopy( signature, 0, outMessage, 0, signature.length ); + System.arraycopy( encryptedMessage, 0, outMessage, signature.length, encryptedMessage.length ); + advanceMessageSequence(); + return outMessage; + } + + public byte[] decryptAndVerifySignedMessage( final byte[] inMessage ) throws NTLMEngineException + { + final byte[] signature = new byte[16]; + System.arraycopy( inMessage, 0, signature, 0, signature.length ); + final byte[] encryptedMessage = new byte[inMessage.length - 16]; + System.arraycopy( inMessage, 16, encryptedMessage, 0, encryptedMessage.length ); + final byte[] cleartextMessage = decrypt( encryptedMessage ); + if ( !validateSignature( signature, cleartextMessage ) ) + { + throw new NTLMEngineException( "Wrong signature" ); + } + advanceMessageSequence(); + return cleartextMessage; + } + + } + + private static byte[] encodeLong( final int value ) + { + final byte[] enc = new byte[4]; + encodeLong( enc, 0, value ); + return enc; + } + + private static void encodeLong( final byte[] buf, final int offset, final int value ) + { + buf[offset + 0] = ( byte ) ( value & 0xff ); + buf[offset + 1] = ( byte ) ( value >> 8 & 0xff ); + buf[offset + 2] = ( byte ) ( value >> 16 & 0xff ); + buf[offset + 3] = ( byte ) ( value >> 24 & 0xff ); + } + + /** + * Creates the NTLMv2 blob from the given target information block and + * client challenge. + * + * @param targetInformation + * The target information block from the Type 2 message. + * @param clientChallenge + * The random 8-byte client challenge. + * + * @return The blob, used in the calculation of the NTLMv2 Response. + */ + private static byte[] createBlob(final byte[] clientChallenge, final byte[] targetInformation, final byte[] timestamp) { + final byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; + final byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + final byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + final byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + final byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8 + + unknown1.length + targetInformation.length + unknown2.length]; + int offset = 0; + System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); + offset += blobSignature.length; + System.arraycopy(reserved, 0, blob, offset, reserved.length); + offset += reserved.length; + System.arraycopy(timestamp, 0, blob, offset, timestamp.length); + offset += timestamp.length; + System.arraycopy(clientChallenge, 0, blob, offset, 8); + offset += 8; + System.arraycopy(unknown1, 0, blob, offset, unknown1.length); + offset += unknown1.length; + System.arraycopy(targetInformation, 0, blob, offset, targetInformation.length); + offset += targetInformation.length; + System.arraycopy(unknown2, 0, blob, offset, unknown2.length); + offset += unknown2.length; + return blob; + } + + /** + * Creates a DES encryption key from the given key material. + * + * @param bytes + * A byte array containing the DES key material. + * @param offset + * The offset in the given byte array at which the 7-byte key + * material starts. + * + * @return A DES encryption key created from the key material starting at + * the specified offset in the given byte array. + */ + private static Key createDESKey(final byte[] bytes, final int offset) { + final byte[] keyBytes = new byte[7]; + System.arraycopy(bytes, offset, keyBytes, 0, 7); + final byte[] material = new byte[8]; + material[0] = keyBytes[0]; + material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); + material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); + material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3); + material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4); + material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5); + material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6); + material[7] = (byte) (keyBytes[6] << 1); + oddParity(material); + return new SecretKeySpec(material, "DES"); + } + + /** + * Applies odd parity to the given byte array. + * + * @param bytes + * The data whose parity bits are to be adjusted for odd parity. + */ + private static void oddParity(final byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + final byte b = bytes[i]; + final boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) + ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0; + if (needsParity) { + bytes[i] |= (byte) 0x01; + } else { + bytes[i] &= (byte) 0xfe; + } + } + } + + /** + * Find the character set based on the flags. + * @param flags is the flags. + * @return the character set. + */ + private static Charset getCharset(final int flags) throws NTLMEngineException + { + if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { + return DEFAULT_CHARSET; + } else { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException( "Unicode not supported" ); + } + return UNICODE_LITTLE_UNMARKED; + } + } + + /** Strip dot suffix from a name */ + private static String stripDotSuffix(final String value) { + if (value == null) { + return null; + } + final int index = value.indexOf('.'); + if (index != -1) { + return value.substring(0, index); + } + return value; + } + + /** Convert host to standard form */ + private static String convertHost(final String host) { + return stripDotSuffix(host); + } + + /** Convert domain to standard form */ + private static String convertDomain(final String domain) { + return stripDotSuffix(domain); + } + + /** NTLM message generation, base class */ + static class NTLMMessage { + /** The current response */ + protected byte[] messageContents = null; + + /** The current output position */ + protected int currentOutputPosition = 0; + + /** Constructor to use when message contents are not yet known */ + NTLMMessage() { + } + + /** Constructor taking a string */ + NTLMMessage(final String messageBody, final int expectedType) throws NTLMEngineException { + this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET)), expectedType); + } + + /** Constructor to use when message bytes are known */ + NTLMMessage(final byte[] message, final int expectedType) throws NTLMEngineException { + messageContents = message; + // Look for NTLM message + if (messageContents.length < SIGNATURE.length) { + throw new NTLMEngineException("NTLM message decoding error - packet too short"); + } + int i = 0; + while (i < SIGNATURE.length) { + if (messageContents[i] != SIGNATURE[i]) { + throw new NTLMEngineException( + "NTLM message expected - instead got unrecognized bytes"); + } + i++; + } + + // Check to be sure there's a type 2 message indicator next + final int type = readULong(SIGNATURE.length); + if (type != expectedType) { + throw new NTLMEngineException("NTLM type " + Integer.toString(expectedType) + + " message expected - instead got type " + Integer.toString(type)); + } + + currentOutputPosition = messageContents.length; + } + + /** + * Get the length of the signature and flags, so calculations can adjust + * offsets accordingly. + */ + protected int getPreambleLength() { + return SIGNATURE.length + 4; + } + + /** Get the message length */ + protected int getMessageLength() { + return currentOutputPosition; + } + + /** Read a byte from a position within the message buffer */ + protected byte readByte(final int position) throws NTLMEngineException { + if (messageContents.length < position + 1) { + throw new NTLMEngineException("NTLM: Message too short"); + } + return messageContents[position]; + } + + /** Read a bunch of bytes from a position in the message buffer */ + protected void readBytes(final byte[] buffer, final int position) throws NTLMEngineException { + if (messageContents.length < position + buffer.length) { + throw new NTLMEngineException("NTLM: Message too short"); + } + System.arraycopy(messageContents, position, buffer, 0, buffer.length); + } + + /** Read a ushort from a position within the message buffer */ + protected int readUShort(final int position) throws NTLMEngineException { + return NTLMEngineImpl.readUShort(messageContents, position); + } + + /** Read a ulong from a position within the message buffer */ + protected int readULong(final int position) throws NTLMEngineException { + return NTLMEngineImpl.readULong(messageContents, position); + } + + /** Read a security buffer from a position within the message buffer */ + protected byte[] readSecurityBuffer(final int position) throws NTLMEngineException { + return NTLMEngineImpl.readSecurityBuffer(messageContents, position); + } + + /** + * Prepares the object to create a response of the given length. + * + * @param maxlength + * the maximum length of the response to prepare, + * including the type and the signature (which this method + * adds). + */ + protected void prepareResponse(final int maxlength, final int messageType) { + messageContents = new byte[maxlength]; + currentOutputPosition = 0; + addBytes(SIGNATURE); + addULong(messageType); + } + + /** + * Adds the given byte to the response. + * + * @param b + * the byte to add. + */ + protected void addByte(final byte b) { + messageContents[currentOutputPosition] = b; + currentOutputPosition++; + } + + /** + * Adds the given bytes to the response. + * + * @param bytes + * the bytes to add. + */ + protected void addBytes(final byte[] bytes) { + if (bytes == null) { + return; + } + for (final byte b : bytes) { + messageContents[currentOutputPosition] = b; + currentOutputPosition++; + } + } + + /** Adds a USHORT to the response */ + protected void addUShort(final int value) { + addByte((byte) (value & 0xff)); + addByte((byte) (value >> 8 & 0xff)); + } + + /** Adds a ULong to the response */ + protected void addULong(final int value) { + addByte((byte) (value & 0xff)); + addByte((byte) (value >> 8 & 0xff)); + addByte((byte) (value >> 16 & 0xff)); + addByte((byte) (value >> 24 & 0xff)); + } + + /** + * Returns the response that has been generated after shrinking the + * array if required and base64 encodes the response. + * + * @return The response as above. + */ + public String getResponse() { + return new String(Base64.encodeBase64(getBytes()), Consts.ASCII); + } + + public byte[] getBytes() { + if (messageContents == null) { + buildMessage(); + } + final byte[] resp; + if ( messageContents.length > currentOutputPosition ) { + final byte[] tmp = new byte[currentOutputPosition]; + System.arraycopy( messageContents, 0, tmp, 0, currentOutputPosition ); + messageContents = tmp; + } + return messageContents; + } + + protected void buildMessage() { + throw new RuntimeException("Message builder not implemented for "+getClass().getName()); + } + } + + /** Type 1 message assembly class */ + static class Type1Message extends NTLMMessage { + + private final byte[] hostBytes; + private final byte[] domainBytes; + private final int flags; + + Type1Message(final String domain, final String host) throws NTLMEngineException { + this(domain, host, null); + } + + Type1Message(final String domain, final String host, final Integer flags) throws NTLMEngineException { + super(); + this.flags = ((flags == null)?getDefaultFlags():flags); + + // Strip off domain name from the host! + final String unqualifiedHost = convertHost(host); + // Use only the base domain name! + final String unqualifiedDomain = convertDomain(domain); + + hostBytes = unqualifiedHost != null ? + unqualifiedHost.getBytes(UNICODE_LITTLE_UNMARKED) : null; + domainBytes = unqualifiedDomain != null ? + unqualifiedDomain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED) : null; + } + + Type1Message() { + super(); + hostBytes = null; + domainBytes = null; + flags = getDefaultFlags(); + } + + private int getDefaultFlags() { + return + //FLAG_WORKSTATION_PRESENT | + //FLAG_DOMAIN_PRESENT | + + // Required flags + //FLAG_REQUEST_LAN_MANAGER_KEY | + FLAG_REQUEST_NTLMv1 | + FLAG_REQUEST_NTLM2_SESSION | + + // Protocol version request + FLAG_REQUEST_VERSION | + + // Recommended privacy settings + FLAG_REQUEST_ALWAYS_SIGN | + //FLAG_REQUEST_SEAL | + //FLAG_REQUEST_SIGN | + + // These must be set according to documentation, based on use of SEAL above + FLAG_REQUEST_128BIT_KEY_EXCH | + FLAG_REQUEST_56BIT_ENCRYPTION | + //FLAG_REQUEST_EXPLICIT_KEY_EXCH | + + FLAG_REQUEST_UNICODE_ENCODING; + + } + + /** + * Getting the response involves building the message before returning + * it + */ + @Override + protected void buildMessage() { + int domainBytesLength = 0; + if ( domainBytes != null ) { + domainBytesLength = domainBytes.length; + } + int hostBytesLength = 0; + if ( hostBytes != null ) { + hostBytesLength = hostBytes.length; + } + + // Now, build the message. Calculate its length first, including + // signature or type. + final int finalLength = 32 + 8 + hostBytesLength + domainBytesLength; + + // Set up the response. This will initialize the signature, message + // type, and flags. + prepareResponse(finalLength, 1); + + // Flags. These are the complete set of flags we support. + addULong(flags); + + // Domain length (two times). + addUShort(domainBytesLength); + addUShort(domainBytesLength); + + // Domain offset. + addULong(hostBytesLength + 32 + 8); + + // Host length (two times). + addUShort(hostBytesLength); + addUShort(hostBytesLength); + + // Host offset (always 32 + 8). + addULong(32 + 8); + + // Version + addUShort(0x0105); + // Build + addULong(2600); + // NTLM revision + addUShort(0x0f00); + + // Host (workstation) String. + if (hostBytes != null) { + addBytes(hostBytes); + } + // Domain String. + if (domainBytes != null) { + addBytes(domainBytes); + } + } + + } + + /** Type 2 message class */ + static class Type2Message extends NTLMMessage { + protected final byte[] challenge; + protected String target; + protected byte[] targetInfo; + protected final int flags; + + Type2Message(final String messageBody) throws NTLMEngineException { + this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET))); + } + + Type2Message(final byte[] message) throws NTLMEngineException { + super(message, 2); + + // Type 2 message is laid out as follows: + // First 8 bytes: NTLMSSP[0] + // Next 4 bytes: Ulong, value 2 + // Next 8 bytes, starting at offset 12: target field (2 ushort lengths, 1 ulong offset) + // Next 4 bytes, starting at offset 20: Flags, e.g. 0x22890235 + // Next 8 bytes, starting at offset 24: Challenge + // Next 8 bytes, starting at offset 32: ??? (8 bytes of zeros) + // Next 8 bytes, starting at offset 40: targetinfo field (2 ushort lengths, 1 ulong offset) + // Next 2 bytes, major/minor version number (e.g. 0x05 0x02) + // Next 8 bytes, build number + // Next 2 bytes, protocol version number (e.g. 0x00 0x0f) + // Next, various text fields, and a ushort of value 0 at the end + + // Parse out the rest of the info we need from the message + // The nonce is the 8 bytes starting from the byte in position 24. + challenge = new byte[8]; + readBytes(challenge, 24); + + flags = readULong(20); + + // Do the target! + target = null; + // The TARGET_DESIRED flag is said to not have understood semantics + // in Type2 messages, so use the length of the packet to decide + // how to proceed instead + if (getMessageLength() >= 12 + 8) { + final byte[] bytes = readSecurityBuffer(12); + if (bytes.length != 0) { + target = new String(bytes, getCharset(flags)); + } + } + + // Do the target info! + targetInfo = null; + // TARGET_DESIRED flag cannot be relied on, so use packet length + if (getMessageLength() >= 40 + 8) { + final byte[] bytes = readSecurityBuffer(40); + if (bytes.length != 0) { + targetInfo = bytes; + } + } + } + + /** Retrieve the challenge */ + byte[] getChallenge() { + return challenge; + } + + /** Retrieve the target */ + String getTarget() { + return target; + } + + /** Retrieve the target info */ + byte[] getTargetInfo() { + return targetInfo; + } + + /** Retrieve the response flags */ + int getFlags() { + return flags; + } + + } + + /** Type 3 message assembly class */ + static class Type3Message extends NTLMMessage { + // For mic computation + protected final byte[] type1Message; + protected final byte[] type2Message; + // Response flags from the type2 message + protected final int type2Flags; + + protected final byte[] domainBytes; + protected final byte[] hostBytes; + protected final byte[] userBytes; + + protected byte[] lmResp; + protected byte[] ntResp; + protected final byte[] sessionKey; + protected final byte[] exportedSessionKey; + + protected final boolean computeMic; + + /** More primitive constructor: don't include cert or previous messages. + */ + Type3Message(final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation) + throws NTLMEngineException { + this(domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); + } + + /** More primitive constructor: don't include cert or previous messages. + */ + Type3Message(final Random random, final long currentTime, + final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation) + throws NTLMEngineException { + this(random, currentTime, domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); + } + + /** Constructor. Pass the arguments we will need */ + Type3Message(final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation, + final Certificate peerServerCertificate, + final byte[] type1Message, + final byte[] type2Message) + throws NTLMEngineException { + this(RND_GEN, System.currentTimeMillis(), domain, host, user, password, nonce, type2Flags, target, targetInformation, peerServerCertificate, type1Message, type2Message); + } + + /** Constructor. Pass the arguments we will need */ + Type3Message(final Random random, final long currentTime, + final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation, + final Certificate peerServerCertificate, + final byte[] type1Message, + final byte[] type2Message) + throws NTLMEngineException { + + if (random == null) { + throw new NTLMEngineException("Random generator not available"); + } + + // Save the flags + this.type2Flags = type2Flags; + this.type1Message = type1Message; + this.type2Message = type2Message; + + // Strip off domain name from the host! + final String unqualifiedHost = convertHost(host); + // Use only the base domain name! + final String unqualifiedDomain = convertDomain(domain); + + byte[] responseTargetInformation = targetInformation; + if (peerServerCertificate != null) { + responseTargetInformation = addGssMicAvsToTargetInfo(targetInformation, peerServerCertificate); + computeMic = true; + } else { + computeMic = false; + } + + // Create a cipher generator class. Use domain BEFORE it gets modified! + final CipherGen gen = new CipherGen(random, currentTime, + unqualifiedDomain, + user, + password, + nonce, + target, + responseTargetInformation); + + // Use the new code to calculate the responses, including v2 if that + // seems warranted. + byte[] userSessionKey; + try { + // This conditional may not work on Windows Server 2008 R2 and above, where it has not yet + // been tested + if (((type2Flags & FLAG_TARGETINFO_PRESENT) != 0) && + targetInformation != null && target != null) { + // NTLMv2 + ntResp = gen.getNTLMv2Response(); + lmResp = gen.getLMv2Response(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getNTLMv2UserSessionKey(); + } + } else { + // NTLMv1 + if ((type2Flags & FLAG_REQUEST_NTLM2_SESSION) != 0) { + // NTLM2 session stuff is requested + ntResp = gen.getNTLM2SessionResponse(); + lmResp = gen.getLM2SessionResponse(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getNTLM2SessionResponseUserSessionKey(); + } + } else { + ntResp = gen.getNTLMResponse(); + lmResp = gen.getLMResponse(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getNTLMUserSessionKey(); + } + } + } + } catch (final NTLMEngineException e) { + // This likely means we couldn't find the MD4 hash algorithm - + // fail back to just using LM + ntResp = new byte[0]; + lmResp = gen.getLMResponse(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getLMUserSessionKey(); + } + } + + if ((type2Flags & FLAG_REQUEST_SIGN) != 0) { + if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) { + exportedSessionKey = gen.getSecondaryKey(); + sessionKey = RC4(exportedSessionKey, userSessionKey); + } else { + sessionKey = userSessionKey; + exportedSessionKey = sessionKey; + } + } else { + if (computeMic) { + throw new NTLMEngineException("Cannot sign/seal: no exported session key"); + } + sessionKey = null; + exportedSessionKey = null; + } + final Charset charset = getCharset(type2Flags); + hostBytes = unqualifiedHost != null ? unqualifiedHost.getBytes(charset) : null; + domainBytes = unqualifiedDomain != null ? unqualifiedDomain + .toUpperCase(Locale.ROOT).getBytes(charset) : null; + userBytes = user.getBytes(charset); + } + + public byte[] getEncryptedRandomSessionKey() { + return sessionKey; + } + + public byte[] getExportedSessionKey() { + return exportedSessionKey; + } + + /** Assemble the response */ + @Override + protected void buildMessage() { + final int ntRespLen = ntResp.length; + final int lmRespLen = lmResp.length; + + final int domainLen = domainBytes != null ? domainBytes.length : 0; + final int hostLen = hostBytes != null ? hostBytes.length: 0; + final int userLen = userBytes.length; + final int sessionKeyLen; + if (sessionKey != null) { + sessionKeyLen = sessionKey.length; + } else { + sessionKeyLen = 0; + } + + // Calculate the layout within the packet + final int lmRespOffset = 72 + // allocate space for the version + ( computeMic ? 16 : 0 ); // and MIC + final int ntRespOffset = lmRespOffset + lmRespLen; + final int domainOffset = ntRespOffset + ntRespLen; + final int userOffset = domainOffset + domainLen; + final int hostOffset = userOffset + userLen; + final int sessionKeyOffset = hostOffset + hostLen; + final int finalLength = sessionKeyOffset + sessionKeyLen; + + // Start the response. Length includes signature and type + prepareResponse(finalLength, 3); + + // LM Resp Length (twice) + addUShort(lmRespLen); + addUShort(lmRespLen); + + // LM Resp Offset + addULong(lmRespOffset); + + // NT Resp Length (twice) + addUShort(ntRespLen); + addUShort(ntRespLen); + + // NT Resp Offset + addULong(ntRespOffset); + + // Domain length (twice) + addUShort(domainLen); + addUShort(domainLen); + + // Domain offset. + addULong(domainOffset); + + // User Length (twice) + addUShort(userLen); + addUShort(userLen); + + // User offset + addULong(userOffset); + + // Host length (twice) + addUShort(hostLen); + addUShort(hostLen); + + // Host offset + addULong(hostOffset); + + // Session key length (twice) + addUShort(sessionKeyLen); + addUShort(sessionKeyLen); + + // Session key offset + addULong(sessionKeyOffset); + + // Flags. + addULong( + /* + //FLAG_WORKSTATION_PRESENT | + //FLAG_DOMAIN_PRESENT | + + // Required flags + (type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) | + (type2Flags & FLAG_REQUEST_NTLMv1) | + (type2Flags & FLAG_REQUEST_NTLM2_SESSION) | + + // Protocol version request + FLAG_REQUEST_VERSION | + + // Recommended privacy settings + (type2Flags & FLAG_REQUEST_ALWAYS_SIGN) | + (type2Flags & FLAG_REQUEST_SEAL) | + (type2Flags & FLAG_REQUEST_SIGN) | + + // These must be set according to documentation, based on use of SEAL above + (type2Flags & FLAG_REQUEST_128BIT_KEY_EXCH) | + (type2Flags & FLAG_REQUEST_56BIT_ENCRYPTION) | + (type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) | + + (type2Flags & FLAG_TARGETINFO_PRESENT) | + (type2Flags & FLAG_REQUEST_UNICODE_ENCODING) | + (type2Flags & FLAG_REQUEST_TARGET) + */ + type2Flags + ); + + // Version + addUShort(0x0105); + // Build + addULong(2600); + // NTLM revision + addUShort(0x0f00); + + int micPosition = -1; + if ( computeMic ) { + micPosition = currentOutputPosition; + currentOutputPosition += 16; + } + + // Add the actual data + addBytes(lmResp); + addBytes(ntResp); + addBytes(domainBytes); + addBytes(userBytes); + addBytes(hostBytes); + if (sessionKey != null) { + addBytes(sessionKey); + } + + // Write the mic back into its slot in the message + + if (computeMic) { + // Computation of message integrity code (MIC) as specified in [MS-NLMP] section 3.2.5.1.2. + final HMACMD5 hmacMD5 = new HMACMD5( exportedSessionKey ); + hmacMD5.update( type1Message ); + hmacMD5.update( type2Message ); + hmacMD5.update( messageContents ); + final byte[] mic = hmacMD5.getOutput(); + System.arraycopy( mic, 0, messageContents, micPosition, mic.length ); + } + } + + /** + * Add GSS channel binding hash and MIC flag to the targetInfo. + * Looks like this is needed if we want to use exported session key for GSS wrapping. + */ + private byte[] addGssMicAvsToTargetInfo( final byte[] originalTargetInfo, + final Certificate peerServerCertificate ) throws NTLMEngineException + { + final byte[] newTargetInfo = new byte[originalTargetInfo.length + 8 + 20]; + final int appendLength = originalTargetInfo.length - 4; // last tag is MSV_AV_EOL, do not copy that + System.arraycopy( originalTargetInfo, 0, newTargetInfo, 0, appendLength ); + writeUShort( newTargetInfo, MSV_AV_FLAGS, appendLength ); + writeUShort( newTargetInfo, 4, appendLength + 2 ); + writeULong( newTargetInfo, MSV_AV_FLAGS_MIC, appendLength + 4 ); + writeUShort( newTargetInfo, MSV_AV_CHANNEL_BINDINGS, appendLength + 8 ); + writeUShort( newTargetInfo, 16, appendLength + 10 ); + + final byte[] channelBindingsHash; + try + { + final byte[] certBytes = peerServerCertificate.getEncoded(); + final MessageDigest sha256 = MessageDigest.getInstance( "SHA-256" ); + final byte[] certHashBytes = sha256.digest( certBytes ); + final byte[] channelBindingStruct = new byte[16 + 4 + MAGIC_TLS_SERVER_ENDPOINT.length + + certHashBytes.length]; + writeULong( channelBindingStruct, 0x00000035, 16 ); + System.arraycopy( MAGIC_TLS_SERVER_ENDPOINT, 0, channelBindingStruct, 20, + MAGIC_TLS_SERVER_ENDPOINT.length ); + System.arraycopy( certHashBytes, 0, channelBindingStruct, 20 + MAGIC_TLS_SERVER_ENDPOINT.length, + certHashBytes.length ); + final MessageDigest md5 = getMD5(); + channelBindingsHash = md5.digest( channelBindingStruct ); + } + catch ( final CertificateEncodingException e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + catch ( final NoSuchAlgorithmException e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + + System.arraycopy( channelBindingsHash, 0, newTargetInfo, appendLength + 12, 16 ); + return newTargetInfo; + } + + } + + static void writeUShort(final byte[] buffer, final int value, final int offset) { + buffer[offset] = ( byte ) ( value & 0xff ); + buffer[offset + 1] = ( byte ) ( value >> 8 & 0xff ); + } + + static void writeULong(final byte[] buffer, final int value, final int offset) { + buffer[offset] = (byte) (value & 0xff); + buffer[offset + 1] = (byte) (value >> 8 & 0xff); + buffer[offset + 2] = (byte) (value >> 16 & 0xff); + buffer[offset + 3] = (byte) (value >> 24 & 0xff); + } + + static int F(final int x, final int y, final int z) { + return ((x & y) | (~x & z)); + } + + static int G(final int x, final int y, final int z) { + return ((x & y) | (x & z) | (y & z)); + } + + static int H(final int x, final int y, final int z) { + return (x ^ y ^ z); + } + + static int rotintlft(final int val, final int numbits) { + return ((val << numbits) | (val >>> (32 - numbits))); + } + + static MessageDigest getMD5() { + try { + return MessageDigest.getInstance("MD5"); + } catch (final NoSuchAlgorithmException ex) { + throw new RuntimeException("MD5 message digest doesn't seem to exist - fatal error: "+ex.getMessage(), ex); + } + } + + /** + * Cryptography support - MD4. The following class was based loosely on the + * RFC and on code found at http://www.cs.umd.edu/~harry/jotp/src/md.java. + * Code correctness was verified by looking at MD4.java from the jcifs + * library (http://jcifs.samba.org). It was massaged extensively to the + * final form found here by Karl Wright (kwright@metacarta.com). + */ + static class MD4 { + protected int A = 0x67452301; + protected int B = 0xefcdab89; + protected int C = 0x98badcfe; + protected int D = 0x10325476; + protected long count = 0L; + protected final byte[] dataBuffer = new byte[64]; + + MD4() { + } + + void update(final byte[] input) { + // We always deal with 512 bits at a time. Correspondingly, there is + // a buffer 64 bytes long that we write data into until it gets + // full. + int curBufferPos = (int) (count & 63L); + int inputIndex = 0; + while (input.length - inputIndex + curBufferPos >= dataBuffer.length) { + // We have enough data to do the next step. Do a partial copy + // and a transform, updating inputIndex and curBufferPos + // accordingly + final int transferAmt = dataBuffer.length - curBufferPos; + System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); + count += transferAmt; + curBufferPos = 0; + inputIndex += transferAmt; + processBuffer(); + } + + // If there's anything left, copy it into the buffer and leave it. + // We know there's not enough left to process. + if (inputIndex < input.length) { + final int transferAmt = input.length - inputIndex; + System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); + count += transferAmt; + curBufferPos += transferAmt; + } + } + + byte[] getOutput() { + // Feed pad/length data into engine. This must round out the input + // to a multiple of 512 bits. + final int bufferIndex = (int) (count & 63L); + final int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); + final byte[] postBytes = new byte[padLen + 8]; + // Leading 0x80, specified amount of zero padding, then length in + // bits. + postBytes[0] = (byte) 0x80; + // Fill out the last 8 bytes with the length + for (int i = 0; i < 8; i++) { + postBytes[padLen + i] = (byte) ((count * 8) >>> (8 * i)); + } + + // Update the engine + update(postBytes); + + // Calculate final result + final byte[] result = new byte[16]; + writeULong(result, A, 0); + writeULong(result, B, 4); + writeULong(result, C, 8); + writeULong(result, D, 12); + return result; + } + + protected void processBuffer() { + // Convert current buffer to 16 ulongs + final int[] d = new int[16]; + + for (int i = 0; i < 16; i++) { + d[i] = (dataBuffer[i * 4] & 0xff) + ((dataBuffer[i * 4 + 1] & 0xff) << 8) + + ((dataBuffer[i * 4 + 2] & 0xff) << 16) + + ((dataBuffer[i * 4 + 3] & 0xff) << 24); + } + + // Do a round of processing + final int AA = A; + final int BB = B; + final int CC = C; + final int DD = D; + round1(d); + round2(d); + round3(d); + A += AA; + B += BB; + C += CC; + D += DD; + + } + + protected void round1(final int[] d) { + A = rotintlft((A + F(B, C, D) + d[0]), 3); + D = rotintlft((D + F(A, B, C) + d[1]), 7); + C = rotintlft((C + F(D, A, B) + d[2]), 11); + B = rotintlft((B + F(C, D, A) + d[3]), 19); + + A = rotintlft((A + F(B, C, D) + d[4]), 3); + D = rotintlft((D + F(A, B, C) + d[5]), 7); + C = rotintlft((C + F(D, A, B) + d[6]), 11); + B = rotintlft((B + F(C, D, A) + d[7]), 19); + + A = rotintlft((A + F(B, C, D) + d[8]), 3); + D = rotintlft((D + F(A, B, C) + d[9]), 7); + C = rotintlft((C + F(D, A, B) + d[10]), 11); + B = rotintlft((B + F(C, D, A) + d[11]), 19); + + A = rotintlft((A + F(B, C, D) + d[12]), 3); + D = rotintlft((D + F(A, B, C) + d[13]), 7); + C = rotintlft((C + F(D, A, B) + d[14]), 11); + B = rotintlft((B + F(C, D, A) + d[15]), 19); + } + + protected void round2(final int[] d) { + A = rotintlft((A + G(B, C, D) + d[0] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[4] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[8] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[12] + 0x5a827999), 13); + + A = rotintlft((A + G(B, C, D) + d[1] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[5] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[9] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[13] + 0x5a827999), 13); + + A = rotintlft((A + G(B, C, D) + d[2] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[6] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[10] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[14] + 0x5a827999), 13); + + A = rotintlft((A + G(B, C, D) + d[3] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[7] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[11] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[15] + 0x5a827999), 13); + + } + + protected void round3(final int[] d) { + A = rotintlft((A + H(B, C, D) + d[0] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[8] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[4] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[12] + 0x6ed9eba1), 15); + + A = rotintlft((A + H(B, C, D) + d[2] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[10] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[6] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[14] + 0x6ed9eba1), 15); + + A = rotintlft((A + H(B, C, D) + d[1] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[9] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[5] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[13] + 0x6ed9eba1), 15); + + A = rotintlft((A + H(B, C, D) + d[3] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[11] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[7] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[15] + 0x6ed9eba1), 15); + + } + + } + + /** + * Cryptography support - HMACMD5 - algorithmically based on various web + * resources by Karl Wright + */ + static class HMACMD5 { + protected final byte[] ipad; + protected final byte[] opad; + protected final MessageDigest md5; + + HMACMD5(final byte[] input) { + byte[] key = input; + md5 = getMD5(); + + // Initialize the pad buffers with the key + ipad = new byte[64]; + opad = new byte[64]; + + int keyLength = key.length; + if (keyLength > 64) { + // Use MD5 of the key instead, as described in RFC 2104 + md5.update(key); + key = md5.digest(); + keyLength = key.length; + } + int i = 0; + while (i < keyLength) { + ipad[i] = (byte) (key[i] ^ (byte) 0x36); + opad[i] = (byte) (key[i] ^ (byte) 0x5c); + i++; + } + while (i < 64) { + ipad[i] = (byte) 0x36; + opad[i] = (byte) 0x5c; + i++; + } + + // Very important: processChallenge the digest with the ipad buffer + md5.reset(); + md5.update(ipad); + + } + + /** Grab the current digest. This is the "answer". */ + byte[] getOutput() { + final byte[] digest = md5.digest(); + md5.update(opad); + return md5.digest(digest); + } + + /** Update by adding a complete array */ + void update(final byte[] input) { + md5.update(input); + } + + /** Update the algorithm */ + void update(final byte[] input, final int offset, final int length) { + md5.update(input, offset, length); + } + + } + + @Override + public String generateType1Msg( + final String domain, + final String workstation) throws NTLMEngineException { + return getType1Message(workstation, domain); + } + + @Override + public String generateType3Msg( + final String username, + final String password, + final String domain, + final String workstation, + final String challenge) throws NTLMEngineException { + final Type2Message t2m = new Type2Message(challenge); + return getType3Message( + username, + password, + workstation, + domain, + t2m.getChallenge(), + t2m.getFlags(), + t2m.getTarget(), + t2m.getTargetInfo()); + } + +} From 1780ab2bf37ad47fcb819e0a23491f522cb1e67b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 15 Dec 2017 14:15:49 -0700 Subject: [PATCH 167/204] [HTTPCLIENT-1889] org.apache.http.client.utils.URLEncodedUtils.parse() should return a new ArrayList when there are no query parameters. --- RELEASE_NOTES.txt | 4 ++++ .../http/client/utils/URLEncodedUtils.java | 19 +++++++++++-------- .../client/utils/TestURLEncodedUtils.java | 8 ++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 0f79d0d9f2..4f59dd37a3 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -11,6 +11,10 @@ Changelog: * [HTTPCLIENT-1886] Update HttpClient 4.5.x from HttpCore 4.4.7 to 4.4.8 Contributed by Gary Gregory +* [HTTPCLIENT-1889] org.apache.http.client.utils.URLEncodedUtils.parse() + should return a new ArrayList when there are no query parameters. + Contributed by Gary Gregory + Release 4.5.4 ------------------- diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index 8547cf0b4d..02b9735b35 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -24,7 +24,7 @@ * . * */ - + package org.apache.http.client.utils; import java.io.IOException; @@ -37,7 +37,6 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.BitSet; -import java.util.Collections; import java.util.List; import java.util.Scanner; @@ -100,7 +99,7 @@ public static List parse(final URI uri, final Charset charset) { if (query != null && !query.isEmpty()) { return parse(query, charset); } - return Collections.emptyList(); + return createEmptyList(); } /** @@ -120,14 +119,14 @@ public static List parse( Args.notNull(entity, "HTTP entity"); final ContentType contentType = ContentType.get(entity); if (contentType == null || !contentType.getMimeType().equalsIgnoreCase(CONTENT_TYPE)) { - return Collections.emptyList(); + return createEmptyList(); } final long len = entity.getContentLength(); Args.check(len <= Integer.MAX_VALUE, "HTTP entity is too large"); final Charset charset = contentType.getCharset() != null ? contentType.getCharset() : HTTP.DEF_CONTENT_CHARSET; final InputStream instream = entity.getContent(); if (instream == null) { - return Collections.emptyList(); + return createEmptyList(); } final CharArrayBuffer buf; try { @@ -143,7 +142,7 @@ public static List parse( instream.close(); } if (buf.length() == 0) { - return Collections.emptyList(); + return createEmptyList(); } return parse(buf, charset, QP_SEP_A); } @@ -243,7 +242,7 @@ public static void parse( */ public static List parse(final String s, final Charset charset) { if (s == null) { - return Collections.emptyList(); + return createEmptyList(); } final CharArrayBuffer buffer = new CharArrayBuffer(s.length()); buffer.append(s); @@ -266,7 +265,7 @@ public static List parse(final String s, final Charset charset) { */ public static List parse(final String s, final Charset charset, final char... separators) { if (s == null) { - return Collections.emptyList(); + return createEmptyList(); } final CharArrayBuffer buffer = new CharArrayBuffer(s.length()); buffer.append(s); @@ -520,6 +519,10 @@ public static String format( private static final int RADIX = 16; + private static List createEmptyList() { + return new ArrayList(0); + } + private static String urlEncode( final String content, final Charset charset, diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java index b0111ca21d..0041f0f00f 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java @@ -169,6 +169,14 @@ public void testParseInvalidURLCodedContent() throws Exception { assertNameValuePair(result.get(0), "name", "%wa "); } + @Test + public void testEmptyQuery() throws Exception { + final List result = URLEncodedUtils.parse("", Consts.UTF_8); + Assert.assertEquals(0, result.size()); + // [HTTPCLIENT-1889]: + result.add(new BasicNameValuePair("key", "value")); + } + @Test public void testParseEntity() throws Exception { final StringEntity entity = new StringEntity("Name1=Value1"); From e7825a6f13bfcc08fecf353a028173853d0e58f2 Mon Sep 17 00:00:00 2001 From: Sudheera Palihakkara Date: Thu, 11 Jan 2018 14:13:05 +0100 Subject: [PATCH 168/204] HTTPCLIENT-1895: added test case for multi-member GZIP content streams (per RFC 1952) --- .../apache/http/client/entity/TestGZip.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java index f7008b88d7..2f9ba9a685 100644 --- a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java +++ b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java @@ -27,6 +27,7 @@ package org.apache.http.client.entity; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -35,6 +36,7 @@ import org.apache.http.HttpEntity; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; +import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; import org.junit.Assert; @@ -79,4 +81,23 @@ public void testCompressionIOExceptionLeavesOutputStreamOpen() throws Exception } } + @Test + public void testDecompressionWithMultipleGZipStream() throws IOException { + final int[] data = new int[] { + 0x1f, 0x8b, 0x08, 0x08, 0x03, 0xf1, 0x55, 0x5a, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x31, 0x00, + 0x2b, 0x2e, 0x29, 0x4a, 0x4d, 0xcc, 0xd5, 0x35, 0xe4, 0x02, 0x00, 0x03, 0x61, 0xf0, 0x5f, 0x09, + 0x00, 0x00, 0x00, 0x1f, 0x8b, 0x08, 0x08, 0x08, 0xf1, 0x55, 0x5a, 0x00, 0x03, 0x74, 0x65, 0x73, + 0x74, 0x32, 0x00, 0x2b, 0x2e, 0x29, 0x4a, 0x4d, 0xcc, 0xd5, 0x35, 0xe2, 0x02, 0x00, 0xc0, 0x32, + 0xdd, 0x74, 0x09, 0x00, 0x00, 0x00 + }; + final byte[] bytes = new byte[data.length]; + for (int i = 0; i < data.length; i++) { + bytes[i] = (byte) (data[i] & 0xff); + } + + final InputStreamEntity out = new InputStreamEntity(new ByteArrayInputStream(bytes)); + final GzipDecompressingEntity gunZipEntity = new GzipDecompressingEntity(out); + Assert.assertEquals("stream-1\nstream-2\n", EntityUtils.toString(gunZipEntity, Consts.ASCII)); + } + } From 6e372fb531db22c17da095316dbfb5d6051b71b3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Jan 2018 08:55:00 -0700 Subject: [PATCH 169/204] Update NOTICE to 2018. --- NOTICE.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index 73c360ed1c..7b762055a0 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,6 +1,6 @@ -Apache HttpComponents Client -Copyright 1999-2017 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - +Apache HttpComponents Client +Copyright 1999-2018 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + From f1f3a387630a7e3e2d4aeda1744f3e94ca21968a Mon Sep 17 00:00:00 2001 From: Sudheera Palihakkara Date: Sun, 14 Jan 2018 23:49:50 +0800 Subject: [PATCH 170/204] HTTPCLIENT-1690: Avoid merging Content-Encoding headers coming with 304 status to cache entry, port mergeHeaders method from master --- .../impl/client/cache/CacheEntryUpdater.java | 82 ++++++++----------- .../client/cache/TestCacheEntryUpdater.java | 20 +++++ 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java index aa4c83cf43..f18c73cbe6 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java @@ -27,13 +27,10 @@ package org.apache.http.impl.client.cache; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; -import java.util.List; -import java.util.ListIterator; import org.apache.http.Header; +import org.apache.http.HeaderIterator; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.annotation.Contract; @@ -43,6 +40,7 @@ import org.apache.http.client.cache.Resource; import org.apache.http.client.cache.ResourceFactory; import org.apache.http.client.utils.DateUtils; +import org.apache.http.message.HeaderGroup; import org.apache.http.protocol.HTTP; import org.apache.http.util.Args; @@ -102,51 +100,46 @@ public HttpCacheEntry updateCacheEntry( } protected Header[] mergeHeaders(final HttpCacheEntry entry, final HttpResponse response) { - if (entryAndResponseHaveDateHeader(entry, response) && entryDateHeaderNewerThenResponse(entry, response)) { // Don't merge headers, keep the entry's headers as they are newer. return entry.getAllHeaders(); } - final List
          cacheEntryHeaderList = new ArrayList
          (Arrays.asList(entry - .getAllHeaders())); - removeCacheHeadersThatMatchResponse(cacheEntryHeaderList, response); - removeCacheEntry1xxWarnings(cacheEntryHeaderList, entry); - cacheEntryHeaderList.addAll(Arrays.asList(response.getAllHeaders())); - - return cacheEntryHeaderList.toArray(new Header[cacheEntryHeaderList.size()]); - } - - private void removeCacheHeadersThatMatchResponse(final List
          cacheEntryHeaderList, - final HttpResponse response) { - for (final Header responseHeader : response.getAllHeaders()) { - final ListIterator
          cacheEntryHeaderListIter = cacheEntryHeaderList.listIterator(); - - while (cacheEntryHeaderListIter.hasNext()) { - final String cacheEntryHeaderName = cacheEntryHeaderListIter.next().getName(); + final HeaderGroup headerGroup = new HeaderGroup(); + headerGroup.setHeaders(entry.getAllHeaders()); + // Remove cache headers that match response + for (final HeaderIterator it = response.headerIterator(); it.hasNext(); ) { + final Header responseHeader = it.nextHeader(); + // Since we do not expect a content in a 304 response, should retain the original Content-Encoding header + if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())) { + continue; + } + final Header[] matchingHeaders = headerGroup.getHeaders(responseHeader.getName()); + for (final Header matchingHeader : matchingHeaders) { + headerGroup.removeHeader(matchingHeader); + } - if (cacheEntryHeaderName.equals(responseHeader.getName())) { - cacheEntryHeaderListIter.remove(); + } + // remove cache entry 1xx warnings + for (final HeaderIterator it = headerGroup.iterator(); it.hasNext(); ) { + final Header cacheHeader = it.nextHeader(); + if (HeaderConstants.WARNING.equalsIgnoreCase(cacheHeader.getName())) { + final String warningValue = cacheHeader.getValue(); + if (warningValue != null && warningValue.startsWith("1")) { + it.remove(); } } } - } - - private void removeCacheEntry1xxWarnings(final List
          cacheEntryHeaderList, final HttpCacheEntry entry) { - final ListIterator
          cacheEntryHeaderListIter = cacheEntryHeaderList.listIterator(); - - while (cacheEntryHeaderListIter.hasNext()) { - final String cacheEntryHeaderName = cacheEntryHeaderListIter.next().getName(); - - if (HeaderConstants.WARNING.equals(cacheEntryHeaderName)) { - for (final Header cacheEntryWarning : entry.getHeaders(HeaderConstants.WARNING)) { - if (cacheEntryWarning.getValue().startsWith("1")) { - cacheEntryHeaderListIter.remove(); - } - } + for (final HeaderIterator it = response.headerIterator(); it.hasNext(); ) { + final Header responseHeader = it.nextHeader(); + // Since we do not expect a content in a 304 response, should avoid updating Content-Encoding header + if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())) { + continue; } + headerGroup.addHeader(responseHeader); } + return headerGroup.getAllHeaders(); } private boolean entryDateHeaderNewerThenResponse(final HttpCacheEntry entry, final HttpResponse response) { @@ -154,22 +147,13 @@ private boolean entryDateHeaderNewerThenResponse(final HttpCacheEntry entry, fin .getValue()); final Date responseDate = DateUtils.parseDate(response.getFirstHeader(HTTP.DATE_HEADER) .getValue()); - if (entryDate == null || responseDate == null) { - return false; - } - if (!entryDate.after(responseDate)) { - return false; - } - return true; + return entryDate != null && responseDate != null && entryDate.after(responseDate); } private boolean entryAndResponseHaveDateHeader(final HttpCacheEntry entry, final HttpResponse response) { - if (entry.getFirstHeader(HTTP.DATE_HEADER) != null - && response.getFirstHeader(HTTP.DATE_HEADER) != null) { - return true; - } + return entry.getFirstHeader(HTTP.DATE_HEADER) != null + && response.getFirstHeader(HTTP.DATE_HEADER) != null; - return false; } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java index a745010d7e..ed02ce5829 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java @@ -239,6 +239,26 @@ public void cannotUpdateFromANon304OriginResponse() throws Exception { } } + @Test + public void testContentEncodingHeaderIsNotUpdatedByMerge() throws IOException { + final Header[] headers = { + new BasicHeader("Date", DateUtils.formatDate(requestDate)), + new BasicHeader("ETag", "\"etag\""), + new BasicHeader("Content-Encoding", "identity")}; + + entry = HttpTestUtils.makeCacheEntry(headers); + response.setHeaders(new Header[]{ + new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)), + new BasicHeader("Cache-Control", "public"), + new BasicHeader("Content-Encoding", "gzip")}); + + final HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry, + new Date(), new Date(), response); + + final Header[] updatedHeaders = updatedEntry.getAllHeaders(); + headersContain(updatedHeaders, "Content-Encoding", "identity"); + } + private void headersContain(final Header[] headers, final String name, final String value) { for (final Header header : headers) { if (header.getName().equals(name)) { From 0593c591adc9e3854874899fc4edb03808d372c5 Mon Sep 17 00:00:00 2001 From: Sudheera Palihakkara Date: Mon, 15 Jan 2018 18:31:00 +0800 Subject: [PATCH 171/204] HTTPCLIENT-1690: Updated a test case --- .../http/impl/client/cache/TestCacheEntryUpdater.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java index ed02ce5829..a0a873742d 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java @@ -257,6 +257,7 @@ public void testContentEncodingHeaderIsNotUpdatedByMerge() throws IOException { final Header[] updatedHeaders = updatedEntry.getAllHeaders(); headersContain(updatedHeaders, "Content-Encoding", "identity"); + headersNotContain(updatedHeaders, "Content-Encoding", "gzip"); } private void headersContain(final Header[] headers, final String name, final String value) { @@ -270,4 +271,13 @@ private void headersContain(final Header[] headers, final String name, final Str fail("Header [" + name + ": " + value + "] not found in headers."); } + private void headersNotContain(final Header[] headers, final String name, final String value) { + for (final Header header : headers) { + if (header.getName().equals(name)) { + if (header.getValue().equals(value)) { + fail("Header [" + name + ": " + value + "] found in headers where it should not be"); + } + } + } + } } From 443778f2938d29ac7d3d9617de4177dd7845a65f Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 16 Jan 2018 09:25:26 +0100 Subject: [PATCH 172/204] Upgraded HttpCore dependency to version 4.4.9 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6776d50d8e..9ce128d9b0 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 1.6 1.6 - 4.4.8 + 4.4.9 1.2 1.10 2.6.11 From c1c2e9cc82ab818494070709b0ed0b546d2985ed Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 16 Jan 2018 09:51:51 +0100 Subject: [PATCH 173/204] Removed classes committed by mistake --- .../apache/http/impl/auth/CredSspScheme.java | 1126 ----------------- .../http/impl/auth/CredSspSchemeFactory.java | 44 - .../org/apache/http/impl/auth/DebugUtil.java | 96 -- 3 files changed, 1266 deletions(-) delete mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java delete mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java delete mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java deleted file mode 100644 index 9cc5fc84e4..0000000000 --- a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.impl.auth; - - -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import javax.net.ssl.SSLEngineResult.Status; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.http.Consts; -import org.apache.http.Header; -import org.apache.http.HttpRequest; -import org.apache.http.auth.AUTH; -import org.apache.http.auth.AuthenticationException; -import org.apache.http.auth.Credentials; -import org.apache.http.auth.InvalidCredentialsException; -import org.apache.http.auth.MalformedChallengeException; -import org.apache.http.auth.NTCredentials; -import org.apache.http.message.BufferedHeader; -import org.apache.http.protocol.HttpContext; -import org.apache.http.ssl.SSLContexts; -import org.apache.http.util.CharArrayBuffer; -import org.apache.http.util.CharsetUtils; - -/** - *

          - * Client implementation of the CredSSP protocol specified in [MS-CSSP]. - *

          - *

          - * Note: This is implementation is NOT GSS based. It should be. But there is no Java NTLM - * implementation as GSS module. Maybe the NTLMEngine can be converted to GSS and then this - * can be also switched to GSS. In fact it only works in CredSSP+NTLM case. - *

          - *

          - * Based on [MS-CSSP]: Credential Security Support Provider (CredSSP) Protocol (Revision 13.0, 7/14/2016). - * The implementation was inspired by Python CredSSP and NTLM implementation by Jordan Borean. - *

          - */ -public class CredSspScheme extends AuthSchemeBase -{ - private static final Charset UNICODE_LITTLE_UNMARKED = CharsetUtils.lookup( "UnicodeLittleUnmarked" ); - public static final String SCHEME_NAME = "CredSSP"; - - private final Log log = LogFactory.getLog( CredSspScheme.class ); - - enum State - { - // Nothing sent, nothing received - UNINITIATED, - - // We are handshaking. Several messages are exchanged in this state - TLS_HANDSHAKE, - - // TLS handshake finished. Channel established - TLS_HANDSHAKE_FINISHED, - - // NTLM NEGOTIATE message sent (strictly speaking this should be SPNEGO) - NEGO_TOKEN_SENT, - - // NTLM CHALLENGE message received (strictly speaking this should be SPNEGO) - NEGO_TOKEN_RECEIVED, - - // NTLM AUTHENTICATE message sent together with a server public key - PUB_KEY_AUTH_SENT, - - // Server public key authentication message received - PUB_KEY_AUTH_RECEIVED, - - // Credentials message sent. Protocol exchange finished. - CREDENTIALS_SENT; - } - - private State state; - private SSLEngine sslEngine; - private NTLMEngineImpl.Type1Message type1Message; - private NTLMEngineImpl.Type2Message type2Message; - private NTLMEngineImpl.Type3Message type3Message; - private CredSspTsRequest lastReceivedTsRequest; - private NTLMEngineImpl.Handle ntlmOutgoingHandle; - private NTLMEngineImpl.Handle ntlmIncomingHandle; - private byte[] peerPublicKey; - - - public CredSspScheme() { - state = State.UNINITIATED; - } - - - @Override - public String getSchemeName() - { - return SCHEME_NAME; - } - - - @Override - public String getParameter( final String name ) - { - return null; - } - - - @Override - public String getRealm() - { - return null; - } - - - @Override - public boolean isConnectionBased() - { - return true; - } - - - private SSLEngine getSSLEngine() - { - if ( sslEngine == null ) - { - sslEngine = createSSLEngine(); - } - return sslEngine; - } - - - private SSLEngine createSSLEngine() - { - final SSLContext sslContext; - try - { - sslContext = SSLContexts.custom().build(); - } - catch ( final NoSuchAlgorithmException e ) - { - throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); - } - catch ( final KeyManagementException e ) - { - throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); - } - - final X509TrustManager tm = new X509TrustManager() - { - - @Override - public void checkClientTrusted( final X509Certificate[] chain, final String authType ) - throws CertificateException - { - // Nothing to do. - } - - - @Override - public void checkServerTrusted( final X509Certificate[] chain, final String authType ) - throws CertificateException - { - // Nothing to do, accept all. CredSSP server is using its own certificate without any - // binding to the PKI trust chains. The public key is verified as part of the CredSSP - // protocol exchange. - } - - - @Override - public X509Certificate[] getAcceptedIssuers() - { - return null; - } - - }; - try - { - sslContext.init( null, new TrustManager[] - { tm }, null ); - } - catch ( final KeyManagementException e ) - { - throw new RuntimeException( "SSL Context initialization error: " + e.getMessage(), e ); - } - final SSLEngine sslEngine = sslContext.createSSLEngine(); - sslEngine.setUseClientMode( true ); - return sslEngine; - } - - - @Override - protected void parseChallenge( final CharArrayBuffer buffer, final int beginIndex, final int endIndex ) - throws MalformedChallengeException - { - final String inputString = buffer.substringTrimmed( beginIndex, endIndex ); - - if ( inputString.isEmpty() ) - { - if ( state == State.UNINITIATED ) - { - // This is OK, just send out first message. That should start TLS handshake - } - else - { - final String msg = "Received unexpected empty input in state " + state; - log.error( msg ); - throw new MalformedChallengeException( msg ); - } - } - - if ( state == State.TLS_HANDSHAKE ) - { - unwrapHandshake( inputString ); - if ( getSSLEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ) - { - log.trace( "TLS handshake finished" ); - state = State.TLS_HANDSHAKE_FINISHED; - } - } - - if ( state == State.NEGO_TOKEN_SENT ) - { - final ByteBuffer buf = unwrap( inputString ); - state = State.NEGO_TOKEN_RECEIVED; - lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); - } - - if ( state == State.PUB_KEY_AUTH_SENT ) - { - final ByteBuffer buf = unwrap( inputString ); - state = State.PUB_KEY_AUTH_RECEIVED; - lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); - } - } - - - @Override - @Deprecated - public Header authenticate( - final Credentials credentials, - final HttpRequest request ) throws AuthenticationException - { - return authenticate( credentials, request, null ); - } - - - @Override - public Header authenticate( - final Credentials credentials, - final HttpRequest request, - final HttpContext context ) throws AuthenticationException - { - NTCredentials ntcredentials = null; - try - { - ntcredentials = ( NTCredentials ) credentials; - } - catch ( final ClassCastException e ) - { - throw new InvalidCredentialsException( - "Credentials cannot be used for CredSSP authentication: " - + credentials.getClass().getName() ); - } - - String outputString = null; - - if ( state == State.UNINITIATED ) - { - beginTlsHandshake(); - outputString = wrapHandshake(); - state = State.TLS_HANDSHAKE; - - } - else if ( state == State.TLS_HANDSHAKE ) - { - outputString = wrapHandshake(); - - } - else if ( state == State.TLS_HANDSHAKE_FINISHED ) - { - - final int ntlmFlags = getNtlmFlags(); - final ByteBuffer buf = allocateOutBuffer(); - type1Message = new NTLMEngineImpl.Type1Message( - ntcredentials.getDomain(), ntcredentials.getWorkstation(), ntlmFlags); - final byte[] ntlmNegoMessageEncoded = type1Message.getBytes(); - final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmNegoMessageEncoded ); - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.NEGO_TOKEN_SENT; - - } - else if ( state == State.NEGO_TOKEN_RECEIVED ) - { - final ByteBuffer buf = allocateOutBuffer(); - type2Message = new NTLMEngineImpl.Type2Message( - lastReceivedTsRequest.getNegoToken()); - - final Certificate peerServerCertificate = getPeerServerCertificate(); - - type3Message = new NTLMEngineImpl.Type3Message( - ntcredentials.getDomain(), - ntcredentials.getWorkstation(), - ntcredentials.getUserName(), - ntcredentials.getPassword(), - type2Message.getChallenge(), - type2Message.getFlags(), - type2Message.getTarget(), - type2Message.getTargetInfo(), - peerServerCertificate, - type1Message.getBytes(), - type2Message.getBytes()); - - final byte[] ntlmAuthenticateMessageEncoded = type3Message.getBytes(); - - final byte[] exportedSessionKey = type3Message.getExportedSessionKey(); - - ntlmOutgoingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.CLIENT, true); - ntlmIncomingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.SERVER, true); - - final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmAuthenticateMessageEncoded ); - peerPublicKey = getSubjectPublicKeyDer( peerServerCertificate.getPublicKey() ); - final byte[] pubKeyAuth = createPubKeyAuth(); - req.setPubKeyAuth( pubKeyAuth ); - - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.PUB_KEY_AUTH_SENT; - - } - else if ( state == State.PUB_KEY_AUTH_RECEIVED ) - { - verifyPubKeyAuthResponse( lastReceivedTsRequest.getPubKeyAuth() ); - final byte[] authInfo = createAuthInfo( ntcredentials ); - final CredSspTsRequest req = CredSspTsRequest.createAuthInfo( authInfo ); - - final ByteBuffer buf = allocateOutBuffer(); - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.CREDENTIALS_SENT; - } - else - { - throw new AuthenticationException( "Wrong state " + state ); - } - final CharArrayBuffer buffer = new CharArrayBuffer( 32 ); - if ( isProxy() ) - { - buffer.append( AUTH.PROXY_AUTH_RESP ); - } - else - { - buffer.append( AUTH.WWW_AUTH_RESP ); - } - buffer.append( ": CredSSP " ); - buffer.append( outputString ); - return new BufferedHeader( buffer ); - } - - - private int getNtlmFlags() - { - return NTLMEngineImpl.FLAG_REQUEST_OEM_ENCODING | - NTLMEngineImpl.FLAG_REQUEST_SIGN | - NTLMEngineImpl.FLAG_REQUEST_SEAL | - NTLMEngineImpl.FLAG_DOMAIN_PRESENT | - NTLMEngineImpl.FLAG_REQUEST_ALWAYS_SIGN | - NTLMEngineImpl.FLAG_REQUEST_NTLM2_SESSION | - NTLMEngineImpl.FLAG_TARGETINFO_PRESENT | - NTLMEngineImpl.FLAG_REQUEST_VERSION | - NTLMEngineImpl.FLAG_REQUEST_128BIT_KEY_EXCH | - NTLMEngineImpl.FLAG_REQUEST_EXPLICIT_KEY_EXCH | - NTLMEngineImpl.FLAG_REQUEST_56BIT_ENCRYPTION; - } - - - private Certificate getPeerServerCertificate() throws AuthenticationException - { - final Certificate[] peerCertificates; - try - { - peerCertificates = sslEngine.getSession().getPeerCertificates(); - } - catch ( final SSLPeerUnverifiedException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - for ( final Certificate peerCertificate : peerCertificates ) - { - if ( !( peerCertificate instanceof X509Certificate ) ) - { - continue; - } - final X509Certificate peerX509Cerificate = ( X509Certificate ) peerCertificate; - if ( peerX509Cerificate.getBasicConstraints() != -1 ) - { - continue; - } - return peerX509Cerificate; - } - return null; - } - - - private byte[] createPubKeyAuth() throws AuthenticationException - { - return ntlmOutgoingHandle.signAndEncryptMessage( peerPublicKey ); - } - - - private void verifyPubKeyAuthResponse( final byte[] pubKeyAuthResponse ) throws AuthenticationException - { - final byte[] pubKeyReceived = ntlmIncomingHandle.decryptAndVerifySignedMessage( pubKeyAuthResponse ); - - // assert: pubKeyReceived = peerPublicKey + 1 - // The following algorithm is a bit simplified. But due to the ASN.1 encoding the first byte - // of the public key will be 0x30 we can pretty much rely on a fact that there will be no carry - if ( peerPublicKey.length != pubKeyReceived.length ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - if ( ( peerPublicKey[0] + 1 ) != pubKeyReceived[0] ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - for ( int i = 1; i < peerPublicKey.length; i++ ) - { - if ( peerPublicKey[i] != pubKeyReceived[i] ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - } - log.trace( "Received public key response is valid" ); - } - - - private byte[] createAuthInfo( final NTCredentials ntcredentials ) throws AuthenticationException - { - - final byte[] domainBytes = encodeUnicode( ntcredentials.getDomain() ); - final byte[] domainOctetStringBytesLengthBytes = encodeLength( domainBytes.length ); - final int domainNameLength = 1 + domainOctetStringBytesLengthBytes.length + domainBytes.length; - final byte[] domainNameLengthBytes = encodeLength( domainNameLength ); - - final byte[] usernameBytes = encodeUnicode( ntcredentials.getUserName() ); - final byte[] usernameOctetStringBytesLengthBytes = encodeLength( usernameBytes.length ); - final int userNameLength = 1 + usernameOctetStringBytesLengthBytes.length + usernameBytes.length; - final byte[] userNameLengthBytes = encodeLength( userNameLength ); - - final byte[] passwordBytes = encodeUnicode( ntcredentials.getPassword() ); - final byte[] passwordOctetStringBytesLengthBytes = encodeLength( passwordBytes.length ); - final int passwordLength = 1 + passwordOctetStringBytesLengthBytes.length + passwordBytes.length; - final byte[] passwordLengthBytes = encodeLength( passwordLength ); - - final int tsPasswordLength = 1 + domainNameLengthBytes.length + domainNameLength + - 1 + userNameLengthBytes.length + userNameLength + - 1 + passwordLengthBytes.length + passwordLength; - final byte[] tsPasswordLengthBytes = encodeLength( tsPasswordLength ); - final int credentialsOctetStringLength = 1 + tsPasswordLengthBytes.length + tsPasswordLength; - final byte[] credentialsOctetStringLengthBytes = encodeLength( credentialsOctetStringLength ); - final int credentialsLength = 1 + credentialsOctetStringLengthBytes.length + credentialsOctetStringLength; - final byte[] credentialsLengthBytes = encodeLength( credentialsLength ); - final int tsCredentialsLength = 5 + 1 + credentialsLengthBytes.length + credentialsLength; - final byte[] tsCredentialsLengthBytes = encodeLength( tsCredentialsLength ); - - final ByteBuffer buf = ByteBuffer.allocate( 1 + tsCredentialsLengthBytes.length + tsCredentialsLength ); - - // TSCredentials structure [MS-CSSP] section 2.2.1.2 - buf.put( ( byte ) 0x30 ); // seq - buf.put( tsCredentialsLengthBytes ); - - buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // credType tag [0] - buf.put( ( byte ) 3 ); // credType length - buf.put( ( byte ) 0x02 ); // type: INTEGER - buf.put( ( byte ) 1 ); // credType inner length - buf.put( ( byte ) 1 ); // credType value: 1 (password) - - buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // credentials tag [1] - buf.put( credentialsLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( credentialsOctetStringLengthBytes ); - - // TSPasswordCreds structure [MS-CSSP] section 2.2.1.2.1 - buf.put( ( byte ) 0x30 ); // seq - buf.put( tsPasswordLengthBytes ); - - buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // domainName tag [0] - buf.put( domainNameLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( domainOctetStringBytesLengthBytes ); - buf.put( domainBytes ); - - buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // userName tag [1] - buf.put( userNameLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( usernameOctetStringBytesLengthBytes ); - buf.put( usernameBytes ); - - buf.put( ( byte ) ( 0x02 | 0xa0 ) ); // password tag [2] - buf.put( passwordLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( passwordOctetStringBytesLengthBytes ); - buf.put( passwordBytes ); - - final byte[] authInfo = buf.array(); - try - { - return ntlmOutgoingHandle.signAndEncryptMessage( authInfo ); - } - catch ( final NTLMEngineException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - } - - private final static byte[] EMPTYBUFFER = new byte[0]; - - private byte[] encodeUnicode( final String string ) - { - if (string == null) { - return EMPTYBUFFER; - } - return string.getBytes( UNICODE_LITTLE_UNMARKED ); - } - - - private byte[] getSubjectPublicKeyDer( final PublicKey publicKey ) throws AuthenticationException - { - // The publicKey.getEncoded() returns encoded SubjectPublicKeyInfo structure. But the CredSSP expects - // SubjectPublicKey subfield. I have found no easy way how to get just the SubjectPublicKey from - // java.security libraries. So let's use a primitive way and parse it out from the DER. - - try - { - final byte[] encodedPubKeyInfo = publicKey.getEncoded(); - - final ByteBuffer buf = ByteBuffer.wrap( encodedPubKeyInfo ); - getByteAndAssert( buf, 0x30, "initial sequence" ); - parseLength( buf ); - getByteAndAssert( buf, 0x30, "AlgorithmIdentifier sequence" ); - final int algIdSeqLength = parseLength( buf ); - buf.position( buf.position() + algIdSeqLength ); - getByteAndAssert( buf, 0x03, "subjectPublicKey type" ); - int subjectPublicKeyLegth = parseLength( buf ); - // There may be leading padding byte ... or whatever that is. Skip that. - final byte b = buf.get(); - if ( b == 0 ) - { - subjectPublicKeyLegth--; - } - else - { - buf.position( buf.position() - 1 ); - } - final byte[] subjectPublicKey = new byte[subjectPublicKeyLegth]; - buf.get( subjectPublicKey ); - return subjectPublicKey; - } - catch ( final MalformedChallengeException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - } - - - private void beginTlsHandshake() throws AuthenticationException - { - try - { - getSSLEngine().beginHandshake(); - } - catch ( final SSLException e ) - { - throw new AuthenticationException( "SSL Engine error: " + e.getMessage(), e ); - } - } - - - private ByteBuffer allocateOutBuffer() - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - return ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - } - - - private String wrapHandshake() throws AuthenticationException - { - final ByteBuffer src = allocateOutBuffer(); - src.flip(); - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - // Needs to be twice the size as there may be two wraps during handshake. - // Primitive and inefficient solution, but it works. - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() * 2 ); - while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ) - { - wrap( src, dst ); - } - dst.flip(); - return encodeBase64( dst ); - } - - - private String wrap( final ByteBuffer src ) throws AuthenticationException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() ); - wrap( src, dst ); - dst.flip(); - return encodeBase64( dst ); - } - - - private void wrap( final ByteBuffer src, final ByteBuffer dst ) throws AuthenticationException - { - final SSLEngine sslEngine = getSSLEngine(); - try - { - final SSLEngineResult engineResult = sslEngine.wrap( src, dst ); - if ( engineResult.getStatus() != Status.OK ) - { - throw new AuthenticationException( "SSL Engine error status: " + engineResult.getStatus() ); - } - } - catch ( final SSLException e ) - { - throw new AuthenticationException( "SSL Engine wrap error: " + e.getMessage(), e ); - } - } - - - private void unwrapHandshake( final String inputString ) throws MalformedChallengeException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer src = decodeBase64( inputString ); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) - { - unwrap( src, dst ); - } - } - - - private ByteBuffer unwrap( final String inputString ) throws MalformedChallengeException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer src = decodeBase64( inputString ); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - unwrap( src, dst ); - dst.flip(); - return dst; - } - - - private void unwrap( final ByteBuffer src, final ByteBuffer dst ) throws MalformedChallengeException - { - - try - { - final SSLEngineResult engineResult = sslEngine.unwrap( src, dst ); - if ( engineResult.getStatus() != Status.OK ) - { - throw new MalformedChallengeException( "SSL Engine error status: " + engineResult.getStatus() ); - } - - if ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) - { - final Runnable task = sslEngine.getDelegatedTask(); - task.run(); - } - - } - catch ( final SSLException e ) - { - throw new MalformedChallengeException( "SSL Engine unwrap error: " + e.getMessage(), e ); - } - } - - - private String encodeBase64( final ByteBuffer buffer ) - { - final int limit = buffer.limit(); - final byte[] bytes = new byte[limit]; - buffer.get( bytes ); - return new String(Base64.encodeBase64(bytes), Consts.ASCII); - } - - - private ByteBuffer decodeBase64( final String inputString ) - { - final byte[] inputBytes = Base64.decodeBase64(inputString.getBytes(Consts.ASCII)); - final ByteBuffer buffer = ByteBuffer.wrap( inputBytes ); - return buffer; - } - - - @Override - public boolean isComplete() - { - return state == State.CREDENTIALS_SENT; - } - - /** - * Implementation of the TsRequest structure used in CredSSP protocol. - * It is specified in [MS-CPPS] section 2.2.1. - */ - static class CredSspTsRequest - { - - private static final int VERSION = 3; - - private byte[] negoToken; - private byte[] authInfo; - private byte[] pubKeyAuth; - - - protected CredSspTsRequest() - { - super(); - } - - - public static CredSspTsRequest createNegoToken( final byte[] negoToken ) - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.negoToken = negoToken; - return req; - } - - - public static CredSspTsRequest createAuthInfo( final byte[] authInfo ) - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.authInfo = authInfo; - return req; - } - - - public static CredSspTsRequest createDecoded( final ByteBuffer buf ) throws MalformedChallengeException - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.decode( buf ); - return req; - } - - - public byte[] getNegoToken() - { - return negoToken; - } - - - public void setNegoToken( final byte[] negoToken ) - { - this.negoToken = negoToken; - } - - - public byte[] getAuthInfo() - { - return authInfo; - } - - - public void setAuthInfo( final byte[] authInfo ) - { - this.authInfo = authInfo; - } - - - public byte[] getPubKeyAuth() - { - return pubKeyAuth; - } - - - public void setPubKeyAuth( final byte[] pubKeyAuth ) - { - this.pubKeyAuth = pubKeyAuth; - } - - - public void decode( final ByteBuffer buf ) throws MalformedChallengeException - { - negoToken = null; - authInfo = null; - pubKeyAuth = null; - - getByteAndAssert( buf, 0x30, "initial sequence" ); - parseLength( buf ); - - while ( buf.hasRemaining() ) - { - final int contentTag = getAndAssertContentSpecificTag( buf, "content tag" ); - parseLength( buf ); - switch ( contentTag ) - { - case 0: - processVersion( buf ); - break; - case 1: - parseNegoTokens( buf ); - break; - case 2: - parseAuthInfo( buf ); - break; - case 3: - parsePubKeyAuth( buf ); - break; - case 4: - processErrorCode( buf ); - break; - default: - parseError( buf, "unexpected content tag " + contentTag ); - } - } - } - - - private void processVersion( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x02, "version type" ); - getLengthAndAssert( buf, 1, "version length" ); - getByteAndAssert( buf, VERSION, "wrong protocol version" ); - } - - - private void parseNegoTokens( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x30, "negoTokens sequence" ); - parseLength( buf ); - // I have seen both 0x30LL encoding and 0x30LL0x30LL encoding. Accept both. - byte bufByte = buf.get(); - if ( bufByte == 0x30 ) - { - parseLength( buf ); - bufByte = buf.get(); - } - if ( ( bufByte & 0xff ) != 0xa0 ) - { - parseError( buf, "negoTokens: wrong content-specific tag " + String.format( "%02X", bufByte ) ); - } - parseLength( buf ); - getByteAndAssert( buf, 0x04, "negoToken type" ); - - final int tokenLength = parseLength( buf ); - negoToken = new byte[tokenLength]; - buf.get( negoToken ); - } - - - private void parseAuthInfo( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x04, "authInfo type" ); - final int length = parseLength( buf ); - authInfo = new byte[length]; - buf.get( authInfo ); - } - - - private void parsePubKeyAuth( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x04, "pubKeyAuth type" ); - final int length = parseLength( buf ); - pubKeyAuth = new byte[length]; - buf.get( pubKeyAuth ); - } - - - private void processErrorCode( final ByteBuffer buf ) throws MalformedChallengeException - { - getLengthAndAssert( buf, 3, "error code length" ); - getByteAndAssert( buf, 0x02, "error code type" ); - getLengthAndAssert( buf, 1, "error code length" ); - final byte errorCode = buf.get(); - parseError( buf, "Error code " + errorCode ); - } - - - public void encode( final ByteBuffer buf ) - { - final ByteBuffer inner = ByteBuffer.allocate( buf.capacity() ); - - // version tag [0] - inner.put( ( byte ) ( 0x00 | 0xa0 ) ); - inner.put( ( byte ) 3 ); // length - - inner.put( ( byte ) ( 0x02 ) ); // INTEGER tag - inner.put( ( byte ) 1 ); // length - inner.put( ( byte ) VERSION ); // value - - if ( negoToken != null ) - { - int len = negoToken.length; - final byte[] negoTokenLengthBytes = encodeLength( len ); - len += 1 + negoTokenLengthBytes.length; - final byte[] negoTokenLength1Bytes = encodeLength( len ); - len += 1 + negoTokenLength1Bytes.length; - final byte[] negoTokenLength2Bytes = encodeLength( len ); - len += 1 + negoTokenLength2Bytes.length; - final byte[] negoTokenLength3Bytes = encodeLength( len ); - len += 1 + negoTokenLength3Bytes.length; - final byte[] negoTokenLength4Bytes = encodeLength( len ); - - inner.put( ( byte ) ( 0x01 | 0xa0 ) ); // negoData tag [1] - inner.put( negoTokenLength4Bytes ); // length - - inner.put( ( byte ) ( 0x30 ) ); // SEQUENCE tag - inner.put( negoTokenLength3Bytes ); // length - - inner.put( ( byte ) ( 0x30 ) ); // .. of SEQUENCE tag - inner.put( negoTokenLength2Bytes ); // length - - inner.put( ( byte ) ( 0x00 | 0xa0 ) ); // negoToken tag [0] - inner.put( negoTokenLength1Bytes ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( negoTokenLengthBytes ); // length - - inner.put( negoToken ); - } - - if ( authInfo != null ) - { - final byte[] authInfoEncodedLength = encodeLength( authInfo.length ); - - inner.put( ( byte ) ( 0x02 | 0xa0 ) ); // authInfo tag [2] - inner.put( encodeLength( 1 + authInfoEncodedLength.length + authInfo.length ) ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( authInfoEncodedLength ); - inner.put( authInfo ); - } - - if ( pubKeyAuth != null ) - { - final byte[] pubKeyAuthEncodedLength = encodeLength( pubKeyAuth.length ); - - inner.put( ( byte ) ( 0x03 | 0xa0 ) ); // pubKeyAuth tag [3] - inner.put( encodeLength( 1 + pubKeyAuthEncodedLength.length + pubKeyAuth.length ) ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( pubKeyAuthEncodedLength ); - inner.put( pubKeyAuth ); - } - - inner.flip(); - - // SEQUENCE tag - buf.put( ( byte ) ( 0x10 | 0x20 ) ); - buf.put( encodeLength( inner.limit() ) ); - buf.put( inner ); - } - - - public String debugDump() - { - final StringBuilder sb = new StringBuilder( "TsRequest\n" ); - sb.append( " negoToken:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, negoToken ); - sb.append( "\n" ); - sb.append( " authInfo:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, authInfo ); - sb.append( "\n" ); - sb.append( " pubKeyAuth:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, pubKeyAuth ); - return sb.toString(); - } - - - @Override - public String toString() - { - return "TsRequest(negoToken=" + Arrays.toString( negoToken ) + ", authInfo=" - + Arrays.toString( authInfo ) + ", pubKeyAuth=" + Arrays.toString( pubKeyAuth ) + ")"; - } - } - - static void getByteAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) - throws MalformedChallengeException - { - final byte bufByte = buf.get(); - if ( bufByte != expectedValue ) - { - parseError( buf, errorMessage + expectMessage( expectedValue, bufByte ) ); - } - } - - private static String expectMessage( final int expectedValue, final int realValue ) - { - return "(expected " + String.format( "%02X", expectedValue ) + ", got " + String.format( "%02X", realValue ) - + ")"; - } - - static int parseLength( final ByteBuffer buf ) - { - byte bufByte = buf.get(); - if ( bufByte == 0x80 ) - { - return -1; // infinite - } - if ( ( bufByte & 0x80 ) == 0x80 ) - { - final int size = bufByte & 0x7f; - int length = 0; - for ( int i = 0; i < size; i++ ) - { - bufByte = buf.get(); - length = ( length << 8 ) + ( bufByte & 0xff ); - } - return length; - } - else - { - return bufByte; - } - } - - static void getLengthAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) - throws MalformedChallengeException - { - final int bufLength = parseLength( buf ); - if ( expectedValue != bufLength ) - { - parseError( buf, errorMessage + expectMessage( expectedValue, bufLength ) ); - } - } - - static int getAndAssertContentSpecificTag( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException - { - final byte bufByte = buf.get(); - if ( ( bufByte & 0xe0 ) != 0xa0 ) - { - parseError( buf, errorMessage + ": wrong content-specific tag " + String.format( "%02X", bufByte ) ); - } - final int tag = bufByte & 0x1f; - return tag; - } - - static void parseError( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException - { - throw new MalformedChallengeException( - "Error parsing TsRequest (position:" + buf.position() + "): " + errorMessage ); - } - - static byte[] encodeLength( final int length ) - { - if ( length < 128 ) - { - final byte[] encoded = new byte[1]; - encoded[0] = ( byte ) length; - return encoded; - } - - int size = 1; - - int val = length; - while ( ( val >>>= 8 ) != 0 ) - { - size++; - } - - final byte[] encoded = new byte[1 + size]; - encoded[0] = ( byte ) ( size | 0x80 ); - - int shift = ( size - 1 ) * 8; - for ( int i = 0; i < size; i++ ) - { - encoded[i + 1] = ( byte ) ( length >> shift ); - shift -= 8; - } - - return encoded; - } - -} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java deleted file mode 100644 index 3953b57583..0000000000 --- a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.impl.auth; - - -import org.apache.http.auth.AuthScheme; -import org.apache.http.auth.AuthSchemeProvider; -import org.apache.http.protocol.HttpContext; - - -public class CredSspSchemeFactory implements AuthSchemeProvider -{ - - @Override - public AuthScheme create( final HttpContext context ) - { - return new CredSspScheme(); - } -} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java b/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java deleted file mode 100644 index 2c8110e292..0000000000 --- a/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.impl.auth; - - -import java.nio.ByteBuffer; - - -/** - * Simple debugging utility class for CredSSP and NTLM implementations. - */ -class DebugUtil -{ - - public static String dump( final ByteBuffer buf ) - { - final ByteBuffer dup = buf.duplicate(); - final StringBuilder sb = new StringBuilder( dup.toString() ); - sb.append( ": " ); - while ( dup.position() < dup.limit() ) - { - sb.append( String.format( "%02X ", dup.get() ) ); - } - return sb.toString(); - } - - - public static void dump( final StringBuilder sb, final byte[] bytes ) - { - if ( bytes == null ) - { - sb.append( "null" ); - return; - } - for ( final byte b : bytes ) - { - sb.append( String.format( "%02X ", b ) ); - } - } - - - public static String dump( final byte[] bytes ) - { - final StringBuilder sb = new StringBuilder(); - dump( sb, bytes ); - return sb.toString(); - } - - - public static byte[] fromHex( final String hex ) - { - int i = 0; - final byte[] bytes = new byte[200000]; - int h = 0; - while ( h < hex.length() ) - { - if ( hex.charAt( h ) == ' ' ) - { - h++; - } - final String str = hex.substring( h, h + 2 ); - bytes[i] = ( byte ) Integer.parseInt( str, 16 ); - i++; - h = h + 2; - } - final byte[] outbytes = new byte[i]; - System.arraycopy( bytes, 0, outbytes, 0, i ); - return outbytes; - } - -} From c3e8f46ea7d8daa50481d0e77bbf9285e99e0a90 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 18 Jan 2018 11:56:00 +0100 Subject: [PATCH 174/204] Set API compatibility level to 4.5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9ce128d9b0..1e93e59fa5 100644 --- a/pom.xml +++ b/pom.xml @@ -78,7 +78,7 @@ 1.10.19 4.4.0 1 - 4.4 + 4.5
          From e10c3a6403bed01d57982b8aff22c6399e141a5a Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 18 Jan 2018 12:49:24 +0100 Subject: [PATCH 175/204] Updated release notes for HttpClient 4.5.5 release --- RELEASE_NOTES.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 4f59dd37a3..b4f3ea6bda 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,14 +1,21 @@ Release 4.5.5 ------------------- -HttpClient 4.5.5 (GA) is a maintenance release that fixes a number of defects found since 4.5.4. +HttpClient 4.5.5 (GA) is a maintenance release that fixes a regression introduced +by the previous release causing a NPE in SystemDefaultCredentialsProvider. Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- -* [HTTPCLIENT-1886] Update HttpClient 4.5.x from HttpCore 4.4.7 to 4.4.8 +* [HTTPCLIENT-1690] Avoid merging Content-Encoding headers coming with 304 status to cache entry. + Contributed by Sudheera Palihakkara + +* [HTTPCLIENT-1888] Regression in SystemDefaultCredentialsProvider#getCredentials causing NPE. + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1886] Update HttpClient 4.5.x from HttpCore 4.4.7 to 4.4.9 Contributed by Gary Gregory * [HTTPCLIENT-1889] org.apache.http.client.utils.URLEncodedUtils.parse() From 6f4550ff977a8f497822a17115572dcdb6e715b6 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 18 Jan 2018 13:04:50 +0100 Subject: [PATCH 176/204] HttpClient 4.5.5 release --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index c906c70c25..ab66c526b0 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5-SNAPSHOT + 4.5.5 fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 9d0d0fabf3..ff4399a394 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5-SNAPSHOT + 4.5.5 httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index d46b1cd13a..b1a16c5dea 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5-SNAPSHOT + 4.5.5 httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index ef09a0670f..11e8c149d2 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5-SNAPSHOT + 4.5.5 httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 320ce5ea7a..4db7101b59 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5-SNAPSHOT + 4.5.5 httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index f6184f0d5d..e9ccca7a46 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5-SNAPSHOT + 4.5.5 httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 1e93e59fa5..354fef9661 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.5-SNAPSHOT + 4.5.5 Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 @@ -61,7 +61,7 @@ scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 4.5.5-SNAPSHOT + 4.5.5 From 6374006e102783205c4dcb727b6e18f0c714a6c4 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 22 Jan 2018 09:49:22 +0100 Subject: [PATCH 177/204] Upgraded HttpClient version to 4.5.6-SNAPSHOT --- NOTICE.txt | 12 +- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- .../http/client/utils/URLEncodedUtils.java | 2 +- .../apache/http/impl/auth/NTLMEngineImpl.java | 4204 ++++++++--------- httpmime/pom.xml | 2 +- pom.xml | 4 +- 10 files changed, 2117 insertions(+), 2117 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index 7b762055a0..8d4aa6d986 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,6 +1,6 @@ -Apache HttpComponents Client -Copyright 1999-2018 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - +Apache HttpComponents Client +Copyright 1999-2018 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index ab66c526b0..e02fbbe38f 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5 + 4.5.6-SNAPSHOT fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index ff4399a394..e23149293a 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5 + 4.5.6-SNAPSHOT httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index b1a16c5dea..3e7d012a0d 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5 + 4.5.6-SNAPSHOT httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index 11e8c149d2..cdc948af03 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5 + 4.5.6-SNAPSHOT httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 4db7101b59..56a589dfba 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5 + 4.5.6-SNAPSHOT httpclient Apache HttpClient diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index 02b9735b35..5139d8670f 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -24,7 +24,7 @@ * . * */ - + package org.apache.http.client.utils; import java.io.IOException; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 7e8eb7eac2..1677e777e3 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -1,2102 +1,2102 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.impl.auth; - -import java.nio.charset.Charset; -import org.apache.http.Consts; -import java.security.Key; -import java.security.MessageDigest; -import java.util.Arrays; -import java.util.Locale; -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.Certificate; - -import org.apache.commons.codec.binary.Base64; - -/** - * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM - * authentication protocol. - * - * @since 4.1 - */ -final class NTLMEngineImpl implements NTLMEngine { - - /** Unicode encoding */ - private static final Charset UNICODE_LITTLE_UNMARKED = Charset.forName("UnicodeLittleUnmarked"); - /** Character encoding */ - private static final Charset DEFAULT_CHARSET = Consts.ASCII; - - // Flags we use; descriptions according to: - // http://davenport.sourceforge.net/ntlm.html - // and - // http://msdn.microsoft.com/en-us/library/cc236650%28v=prot.20%29.aspx - // [MS-NLMP] section 2.2.2.5 - static final int FLAG_REQUEST_UNICODE_ENCODING = 0x00000001; // Unicode string encoding requested - static final int FLAG_REQUEST_OEM_ENCODING = 0x00000002; // OEM string encoding requested - static final int FLAG_REQUEST_TARGET = 0x00000004; // Requests target field - static final int FLAG_REQUEST_SIGN = 0x00000010; // Requests all messages have a signature attached, in NEGOTIATE message. - static final int FLAG_REQUEST_SEAL = 0x00000020; // Request key exchange for message confidentiality in NEGOTIATE message. MUST be used in conjunction with 56BIT. - static final int FLAG_REQUEST_LAN_MANAGER_KEY = 0x00000080; // Request Lan Manager key instead of user session key - static final int FLAG_REQUEST_NTLMv1 = 0x00000200; // Request NTLMv1 security. MUST be set in NEGOTIATE and CHALLENGE both - static final int FLAG_DOMAIN_PRESENT = 0x00001000; // Domain is present in message - static final int FLAG_WORKSTATION_PRESENT = 0x00002000; // Workstation is present in message - static final int FLAG_REQUEST_ALWAYS_SIGN = 0x00008000; // Requests a signature block on all messages. Overridden by REQUEST_SIGN and REQUEST_SEAL. - static final int FLAG_REQUEST_NTLM2_SESSION = 0x00080000; // From server in challenge, requesting NTLM2 session security - static final int FLAG_REQUEST_VERSION = 0x02000000; // Request protocol version - static final int FLAG_TARGETINFO_PRESENT = 0x00800000; // From server in challenge message, indicating targetinfo is present - static final int FLAG_REQUEST_128BIT_KEY_EXCH = 0x20000000; // Request explicit 128-bit key exchange - static final int FLAG_REQUEST_EXPLICIT_KEY_EXCH = 0x40000000; // Request explicit key exchange - static final int FLAG_REQUEST_56BIT_ENCRYPTION = 0x80000000; // Must be used in conjunction with SEAL - - // Attribute-value identifiers (AvId) - // according to [MS-NLMP] section 2.2.2.1 - static final int MSV_AV_EOL = 0x0000; // Indicates that this is the last AV_PAIR in the list. - static final int MSV_AV_NB_COMPUTER_NAME = 0x0001; // The server's NetBIOS computer name. - static final int MSV_AV_NB_DOMAIN_NAME = 0x0002; // The server's NetBIOS domain name. - static final int MSV_AV_DNS_COMPUTER_NAME = 0x0003; // The fully qualified domain name (FQDN) of the computer. - static final int MSV_AV_DNS_DOMAIN_NAME = 0x0004; // The FQDN of the domain. - static final int MSV_AV_DNS_TREE_NAME = 0x0005; // The FQDN of the forest. - static final int MSV_AV_FLAGS = 0x0006; // A 32-bit value indicating server or client configuration. - static final int MSV_AV_TIMESTAMP = 0x0007; // server local time - static final int MSV_AV_SINGLE_HOST = 0x0008; // A Single_Host_Data structure. - static final int MSV_AV_TARGET_NAME = 0x0009; // The SPN of the target server. - static final int MSV_AV_CHANNEL_BINDINGS = 0x000A; // A channel bindings hash. - - static final int MSV_AV_FLAGS_ACCOUNT_AUTH_CONSTAINED = 0x00000001; // Indicates to the client that the account authentication is constrained. - static final int MSV_AV_FLAGS_MIC = 0x00000002; // Indicates that the client is providing message integrity in the MIC field in the AUTHENTICATE_MESSAGE. - static final int MSV_AV_FLAGS_UNTRUSTED_TARGET_SPN = 0x00000004; // Indicates that the client is providing a target SPN generated from an untrusted source. - - /** Secure random generator */ - private static final java.security.SecureRandom RND_GEN; - static { - java.security.SecureRandom rnd = null; - try { - rnd = java.security.SecureRandom.getInstance("SHA1PRNG"); - } catch (final Exception ignore) { - } - RND_GEN = rnd; - } - - /** The signature string as bytes in the default encoding */ - private static final byte[] SIGNATURE = getNullTerminatedAsciiString("NTLMSSP"); - - // Key derivation magic strings for the SIGNKEY algorithm defined in - // [MS-NLMP] section 3.4.5.2 - private static final byte[] SIGN_MAGIC_SERVER = getNullTerminatedAsciiString( - "session key to server-to-client signing key magic constant"); - private static final byte[] SIGN_MAGIC_CLIENT = getNullTerminatedAsciiString( - "session key to client-to-server signing key magic constant"); - private static final byte[] SEAL_MAGIC_SERVER = getNullTerminatedAsciiString( - "session key to server-to-client sealing key magic constant"); - private static final byte[] SEAL_MAGIC_CLIENT = getNullTerminatedAsciiString( - "session key to client-to-server sealing key magic constant"); - - // prefix for GSS API channel binding - private static final byte[] MAGIC_TLS_SERVER_ENDPOINT = "tls-server-end-point:".getBytes(Consts.ASCII); - - private static byte[] getNullTerminatedAsciiString( final String source ) - { - final byte[] bytesWithoutNull = source.getBytes(Consts.ASCII); - final byte[] target = new byte[bytesWithoutNull.length + 1]; - System.arraycopy(bytesWithoutNull, 0, target, 0, bytesWithoutNull.length); - target[bytesWithoutNull.length] = (byte) 0x00; - return target; - } - - private static final String TYPE_1_MESSAGE = new Type1Message().getResponse(); - - NTLMEngineImpl() { - } - - /** - * Creates the first message (type 1 message) in the NTLM authentication - * sequence. This message includes the user name, domain and host for the - * authentication session. - * - * @param host - * the computer name of the host requesting authentication. - * @param domain - * The domain to authenticate with. - * @return String the message to add to the HTTP request header. - */ - static String getType1Message(final String host, final String domain) { - // For compatibility reason do not include domain and host in type 1 message - //return new Type1Message(domain, host).getResponse(); - return TYPE_1_MESSAGE; - } - - /** - * Creates the type 3 message using the given server nonce. The type 3 - * message includes all the information for authentication, host, domain, - * username and the result of encrypting the nonce sent by the server using - * the user's password as the key. - * - * @param user - * The user name. This should not include the domain name. - * @param password - * The password. - * @param host - * The host that is originating the authentication request. - * @param domain - * The domain to authenticate within. - * @param nonce - * the 8 byte array the server sent. - * @return The type 3 message. - * @throws NTLMEngineException - * If {@encrypt(byte[],byte[])} fails. - */ - static String getType3Message(final String user, final String password, final String host, final String domain, - final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation) - throws NTLMEngineException { - return new Type3Message(domain, host, user, password, nonce, type2Flags, target, - targetInformation).getResponse(); - } - - /** - * Creates the type 3 message using the given server nonce. The type 3 - * message includes all the information for authentication, host, domain, - * username and the result of encrypting the nonce sent by the server using - * the user's password as the key. - * - * @param user - * The user name. This should not include the domain name. - * @param password - * The password. - * @param host - * The host that is originating the authentication request. - * @param domain - * The domain to authenticate within. - * @param nonce - * the 8 byte array the server sent. - * @return The type 3 message. - * @throws NTLMEngineException - * If {@encrypt(byte[],byte[])} fails. - */ - static String getType3Message(final String user, final String password, final String host, final String domain, - final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation, - final Certificate peerServerCertificate, final byte[] type1Message, final byte[] type2Message) - throws NTLMEngineException { - return new Type3Message(domain, host, user, password, nonce, type2Flags, target, - targetInformation, peerServerCertificate, type1Message, type2Message).getResponse(); - } - - private static int readULong(final byte[] src, final int index) throws NTLMEngineException { - if (src.length < index + 4) { - return 0; - } - return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) - | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); - } - - private static int readUShort(final byte[] src, final int index) throws NTLMEngineException { - if (src.length < index + 2) { - return 0; - } - return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); - } - - private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException { - final int length = readUShort(src, index); - final int offset = readULong(src, index + 4); - if (src.length < offset + length) { - return new byte[length]; - } - final byte[] buffer = new byte[length]; - System.arraycopy(src, offset, buffer, 0, length); - return buffer; - } - - /** Calculate a challenge block */ - private static byte[] makeRandomChallenge(final Random random) throws NTLMEngineException { - final byte[] rval = new byte[8]; - synchronized (random) { - random.nextBytes(rval); - } - return rval; - } - - /** Calculate a 16-byte secondary key */ - private static byte[] makeSecondaryKey(final Random random) throws NTLMEngineException { - final byte[] rval = new byte[16]; - synchronized (random) { - random.nextBytes(rval); - } - return rval; - } - - protected static class CipherGen { - - protected final Random random; - protected final long currentTime; - - protected final String domain; - protected final String user; - protected final String password; - protected final byte[] challenge; - protected final String target; - protected final byte[] targetInformation; - - // Information we can generate but may be passed in (for testing) - protected byte[] clientChallenge; - protected byte[] clientChallenge2; - protected byte[] secondaryKey; - protected byte[] timestamp; - - // Stuff we always generate - protected byte[] lmHash = null; - protected byte[] lmResponse = null; - protected byte[] ntlmHash = null; - protected byte[] ntlmResponse = null; - protected byte[] ntlmv2Hash = null; - protected byte[] lmv2Hash = null; - protected byte[] lmv2Response = null; - protected byte[] ntlmv2Blob = null; - protected byte[] ntlmv2Response = null; - protected byte[] ntlm2SessionResponse = null; - protected byte[] lm2SessionResponse = null; - protected byte[] lmUserSessionKey = null; - protected byte[] ntlmUserSessionKey = null; - protected byte[] ntlmv2UserSessionKey = null; - protected byte[] ntlm2SessionResponseUserSessionKey = null; - protected byte[] lanManagerSessionKey = null; - - @Deprecated - public CipherGen(final String domain, final String user, final String password, - final byte[] challenge, final String target, final byte[] targetInformation, - final byte[] clientChallenge, final byte[] clientChallenge2, - final byte[] secondaryKey, final byte[] timestamp) { - this(RND_GEN, System.currentTimeMillis(), - domain, user, password, challenge, target, targetInformation, - clientChallenge, clientChallenge2, - secondaryKey, timestamp); - } - - public CipherGen(final Random random, final long currentTime, - final String domain, final String user, final String password, - final byte[] challenge, final String target, final byte[] targetInformation, - final byte[] clientChallenge, final byte[] clientChallenge2, - final byte[] secondaryKey, final byte[] timestamp) { - this.random = random; - this.currentTime = currentTime; - - this.domain = domain; - this.target = target; - this.user = user; - this.password = password; - this.challenge = challenge; - this.targetInformation = targetInformation; - this.clientChallenge = clientChallenge; - this.clientChallenge2 = clientChallenge2; - this.secondaryKey = secondaryKey; - this.timestamp = timestamp; - } - - @Deprecated - public CipherGen(final String domain, - final String user, - final String password, - final byte[] challenge, - final String target, - final byte[] targetInformation) { - this(RND_GEN, System.currentTimeMillis(), domain, user, password, challenge, target, targetInformation); - } - - public CipherGen(final Random random, final long currentTime, - final String domain, - final String user, - final String password, - final byte[] challenge, - final String target, - final byte[] targetInformation) { - this(random, currentTime, domain, user, password, challenge, target, targetInformation, null, null, null, null); - } - - /** Calculate and return client challenge */ - public byte[] getClientChallenge() - throws NTLMEngineException { - if (clientChallenge == null) { - clientChallenge = makeRandomChallenge(random); - } - return clientChallenge; - } - - /** Calculate and return second client challenge */ - public byte[] getClientChallenge2() - throws NTLMEngineException { - if (clientChallenge2 == null) { - clientChallenge2 = makeRandomChallenge(random); - } - return clientChallenge2; - } - - /** Calculate and return random secondary key */ - public byte[] getSecondaryKey() - throws NTLMEngineException { - if (secondaryKey == null) { - secondaryKey = makeSecondaryKey(random); - } - return secondaryKey; - } - - /** Calculate and return the LMHash */ - public byte[] getLMHash() - throws NTLMEngineException { - if (lmHash == null) { - lmHash = lmHash(password); - } - return lmHash; - } - - /** Calculate and return the LMResponse */ - public byte[] getLMResponse() - throws NTLMEngineException { - if (lmResponse == null) { - lmResponse = lmResponse(getLMHash(),challenge); - } - return lmResponse; - } - - /** Calculate and return the NTLMHash */ - public byte[] getNTLMHash() - throws NTLMEngineException { - if (ntlmHash == null) { - ntlmHash = ntlmHash(password); - } - return ntlmHash; - } - - /** Calculate and return the NTLMResponse */ - public byte[] getNTLMResponse() - throws NTLMEngineException { - if (ntlmResponse == null) { - ntlmResponse = lmResponse(getNTLMHash(),challenge); - } - return ntlmResponse; - } - - /** Calculate the LMv2 hash */ - public byte[] getLMv2Hash() - throws NTLMEngineException { - if (lmv2Hash == null) { - lmv2Hash = lmv2Hash(domain, user, getNTLMHash()); - } - return lmv2Hash; - } - - /** Calculate the NTLMv2 hash */ - public byte[] getNTLMv2Hash() - throws NTLMEngineException { - if (ntlmv2Hash == null) { - ntlmv2Hash = ntlmv2Hash(domain, user, getNTLMHash()); - } - return ntlmv2Hash; - } - - /** Calculate a timestamp */ - public byte[] getTimestamp() { - if (timestamp == null) { - long time = this.currentTime; - time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch. - time *= 10000; // tenths of a microsecond. - // convert to little-endian byte array. - timestamp = new byte[8]; - for (int i = 0; i < 8; i++) { - timestamp[i] = (byte) time; - time >>>= 8; - } - } - return timestamp; - } - - /** Calculate the NTLMv2Blob */ - public byte[] getNTLMv2Blob() - throws NTLMEngineException { - if (ntlmv2Blob == null) { - ntlmv2Blob = createBlob(getClientChallenge2(), targetInformation, getTimestamp()); - } - return ntlmv2Blob; - } - - /** Calculate the NTLMv2Response */ - public byte[] getNTLMv2Response() - throws NTLMEngineException { - if (ntlmv2Response == null) { - ntlmv2Response = lmv2Response(getNTLMv2Hash(),challenge,getNTLMv2Blob()); - } - return ntlmv2Response; - } - - /** Calculate the LMv2Response */ - public byte[] getLMv2Response() - throws NTLMEngineException { - if (lmv2Response == null) { - lmv2Response = lmv2Response(getLMv2Hash(),challenge,getClientChallenge()); - } - return lmv2Response; - } - - /** Get NTLM2SessionResponse */ - public byte[] getNTLM2SessionResponse() - throws NTLMEngineException { - if (ntlm2SessionResponse == null) { - ntlm2SessionResponse = ntlm2SessionResponse(getNTLMHash(),challenge,getClientChallenge()); - } - return ntlm2SessionResponse; - } - - /** Calculate and return LM2 session response */ - public byte[] getLM2SessionResponse() - throws NTLMEngineException { - if (lm2SessionResponse == null) { - final byte[] clntChallenge = getClientChallenge(); - lm2SessionResponse = new byte[24]; - System.arraycopy(clntChallenge, 0, lm2SessionResponse, 0, clntChallenge.length); - Arrays.fill(lm2SessionResponse, clntChallenge.length, lm2SessionResponse.length, (byte) 0x00); - } - return lm2SessionResponse; - } - - /** Get LMUserSessionKey */ - public byte[] getLMUserSessionKey() - throws NTLMEngineException { - if (lmUserSessionKey == null) { - lmUserSessionKey = new byte[16]; - System.arraycopy(getLMHash(), 0, lmUserSessionKey, 0, 8); - Arrays.fill(lmUserSessionKey, 8, 16, (byte) 0x00); - } - return lmUserSessionKey; - } - - /** Get NTLMUserSessionKey */ - public byte[] getNTLMUserSessionKey() - throws NTLMEngineException { - if (ntlmUserSessionKey == null) { - final MD4 md4 = new MD4(); - md4.update(getNTLMHash()); - ntlmUserSessionKey = md4.getOutput(); - } - return ntlmUserSessionKey; - } - - /** GetNTLMv2UserSessionKey */ - public byte[] getNTLMv2UserSessionKey() - throws NTLMEngineException { - if (ntlmv2UserSessionKey == null) { - final byte[] ntlmv2hash = getNTLMv2Hash(); - final byte[] truncatedResponse = new byte[16]; - System.arraycopy(getNTLMv2Response(), 0, truncatedResponse, 0, 16); - ntlmv2UserSessionKey = hmacMD5(truncatedResponse, ntlmv2hash); - } - return ntlmv2UserSessionKey; - } - - /** Get NTLM2SessionResponseUserSessionKey */ - public byte[] getNTLM2SessionResponseUserSessionKey() - throws NTLMEngineException { - if (ntlm2SessionResponseUserSessionKey == null) { - final byte[] ntlm2SessionResponseNonce = getLM2SessionResponse(); - final byte[] sessionNonce = new byte[challenge.length + ntlm2SessionResponseNonce.length]; - System.arraycopy(challenge, 0, sessionNonce, 0, challenge.length); - System.arraycopy(ntlm2SessionResponseNonce, 0, sessionNonce, challenge.length, ntlm2SessionResponseNonce.length); - ntlm2SessionResponseUserSessionKey = hmacMD5(sessionNonce,getNTLMUserSessionKey()); - } - return ntlm2SessionResponseUserSessionKey; - } - - /** Get LAN Manager session key */ - public byte[] getLanManagerSessionKey() - throws NTLMEngineException { - if (lanManagerSessionKey == null) { - try { - final byte[] keyBytes = new byte[14]; - System.arraycopy(getLMHash(), 0, keyBytes, 0, 8); - Arrays.fill(keyBytes, 8, keyBytes.length, (byte)0xbd); - final Key lowKey = createDESKey(keyBytes, 0); - final Key highKey = createDESKey(keyBytes, 7); - final byte[] truncatedResponse = new byte[8]; - System.arraycopy(getLMResponse(), 0, truncatedResponse, 0, truncatedResponse.length); - Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowPart = des.doFinal(truncatedResponse); - des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highPart = des.doFinal(truncatedResponse); - lanManagerSessionKey = new byte[16]; - System.arraycopy(lowPart, 0, lanManagerSessionKey, 0, lowPart.length); - System.arraycopy(highPart, 0, lanManagerSessionKey, lowPart.length, highPart.length); - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - return lanManagerSessionKey; - } - } - - /** Calculates HMAC-MD5 */ - static byte[] hmacMD5(final byte[] value, final byte[] key) - throws NTLMEngineException { - final HMACMD5 hmacMD5 = new HMACMD5(key); - hmacMD5.update(value); - return hmacMD5.getOutput(); - } - - /** Calculates RC4 */ - static byte[] RC4(final byte[] value, final byte[] key) - throws NTLMEngineException { - try { - final Cipher rc4 = Cipher.getInstance("RC4"); - rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC4")); - return rc4.doFinal(value); - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Calculates the NTLM2 Session Response for the given challenge, using the - * specified password and client challenge. - * - * @return The NTLM2 Session Response. This is placed in the NTLM response - * field of the Type 3 message; the LM response field contains the - * client challenge, null-padded to 24 bytes. - */ - static byte[] ntlm2SessionResponse(final byte[] ntlmHash, final byte[] challenge, - final byte[] clientChallenge) throws NTLMEngineException { - try { - final MessageDigest md5 = getMD5(); - md5.update(challenge); - md5.update(clientChallenge); - final byte[] digest = md5.digest(); - - final byte[] sessionHash = new byte[8]; - System.arraycopy(digest, 0, sessionHash, 0, 8); - return lmResponse(ntlmHash, sessionHash); - } catch (final Exception e) { - if (e instanceof NTLMEngineException) { - throw (NTLMEngineException) e; - } - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Creates the LM Hash of the user's password. - * - * @param password - * The password. - * - * @return The LM Hash of the given password, used in the calculation of the - * LM Response. - */ - private static byte[] lmHash(final String password) throws NTLMEngineException { - try { - final byte[] oemPassword = password.toUpperCase(Locale.ROOT).getBytes(Consts.ASCII); - final int length = Math.min(oemPassword.length, 14); - final byte[] keyBytes = new byte[14]; - System.arraycopy(oemPassword, 0, keyBytes, 0, length); - final Key lowKey = createDESKey(keyBytes, 0); - final Key highKey = createDESKey(keyBytes, 7); - final byte[] magicConstant = "KGS!@#$%".getBytes(Consts.ASCII); - final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowHash = des.doFinal(magicConstant); - des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highHash = des.doFinal(magicConstant); - final byte[] lmHash = new byte[16]; - System.arraycopy(lowHash, 0, lmHash, 0, 8); - System.arraycopy(highHash, 0, lmHash, 8, 8); - return lmHash; - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Creates the NTLM Hash of the user's password. - * - * @param password - * The password. - * - * @return The NTLM Hash of the given password, used in the calculation of - * the NTLM Response and the NTLMv2 and LMv2 Hashes. - */ - private static byte[] ntlmHash(final String password) throws NTLMEngineException { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } - final byte[] unicodePassword = password.getBytes(UNICODE_LITTLE_UNMARKED); - final MD4 md4 = new MD4(); - md4.update(unicodePassword); - return md4.getOutput(); - } - - /** - * Creates the LMv2 Hash of the user's password. - * - * @return The LMv2 Hash, used in the calculation of the NTLMv2 and LMv2 - * Responses. - */ - private static byte[] lmv2Hash(final String domain, final String user, final byte[] ntlmHash) - throws NTLMEngineException { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } - final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); - // Upper case username, upper case domain! - hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); - if (domain != null) { - hmacMD5.update(domain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); - } - return hmacMD5.getOutput(); - } - - /** - * Creates the NTLMv2 Hash of the user's password. - * - * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 and LMv2 - * Responses. - */ - private static byte[] ntlmv2Hash(final String domain, final String user, final byte[] ntlmHash) - throws NTLMEngineException { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException("Unicode not supported"); - } - final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); - // Upper case username, mixed case target!! - hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); - if (domain != null) { - hmacMD5.update(domain.getBytes(UNICODE_LITTLE_UNMARKED)); - } - return hmacMD5.getOutput(); - } - - /** - * Creates the LM Response from the given hash and Type 2 challenge. - * - * @param hash - * The LM or NTLM Hash. - * @param challenge - * The server challenge from the Type 2 message. - * - * @return The response (either LM or NTLM, depending on the provided hash). - */ - private static byte[] lmResponse(final byte[] hash, final byte[] challenge) throws NTLMEngineException { - try { - final byte[] keyBytes = new byte[21]; - System.arraycopy(hash, 0, keyBytes, 0, 16); - final Key lowKey = createDESKey(keyBytes, 0); - final Key middleKey = createDESKey(keyBytes, 7); - final Key highKey = createDESKey(keyBytes, 14); - final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); - des.init(Cipher.ENCRYPT_MODE, lowKey); - final byte[] lowResponse = des.doFinal(challenge); - des.init(Cipher.ENCRYPT_MODE, middleKey); - final byte[] middleResponse = des.doFinal(challenge); - des.init(Cipher.ENCRYPT_MODE, highKey); - final byte[] highResponse = des.doFinal(challenge); - final byte[] lmResponse = new byte[24]; - System.arraycopy(lowResponse, 0, lmResponse, 0, 8); - System.arraycopy(middleResponse, 0, lmResponse, 8, 8); - System.arraycopy(highResponse, 0, lmResponse, 16, 8); - return lmResponse; - } catch (final Exception e) { - throw new NTLMEngineException(e.getMessage(), e); - } - } - - /** - * Creates the LMv2 Response from the given hash, client data, and Type 2 - * challenge. - * - * @param hash - * The NTLMv2 Hash. - * @param clientData - * The client data (blob or client challenge). - * @param challenge - * The server challenge from the Type 2 message. - * - * @return The response (either NTLMv2 or LMv2, depending on the client - * data). - */ - private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData) - throws NTLMEngineException { - final HMACMD5 hmacMD5 = new HMACMD5(hash); - hmacMD5.update(challenge); - hmacMD5.update(clientData); - final byte[] mac = hmacMD5.getOutput(); - final byte[] lmv2Response = new byte[mac.length + clientData.length]; - System.arraycopy(mac, 0, lmv2Response, 0, mac.length); - System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length); - return lmv2Response; - } - - static enum Mode - { - CLIENT, SERVER; - } - - static class Handle - { - final private byte[] exportedSessionKey; - private byte[] signingKey; - private byte[] sealingKey; - private final Cipher rc4; - final Mode mode; - final private boolean isConnection; - int sequenceNumber = 0; - - - Handle( final byte[] exportedSessionKey, final Mode mode, final boolean isConnection ) - throws NTLMEngineException - { - this.exportedSessionKey = exportedSessionKey; - this.isConnection = isConnection; - this.mode = mode; - try - { - final MessageDigest signMd5 = getMD5(); - final MessageDigest sealMd5 = getMD5(); - signMd5.update( exportedSessionKey ); - sealMd5.update( exportedSessionKey ); - if ( mode == Mode.CLIENT ) - { - signMd5.update( SIGN_MAGIC_CLIENT ); - sealMd5.update( SEAL_MAGIC_CLIENT ); - } - else - { - signMd5.update( SIGN_MAGIC_SERVER ); - sealMd5.update( SEAL_MAGIC_SERVER ); - } - signingKey = signMd5.digest(); - sealingKey = sealMd5.digest(); - } - catch ( final Exception e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - rc4 = initCipher(); - } - - public byte[] getSigningKey() - { - return signingKey; - } - - - public byte[] getSealingKey() - { - return sealingKey; - } - - private Cipher initCipher() throws NTLMEngineException - { - final Cipher cipher; - try - { - cipher = Cipher.getInstance( "RC4" ); - if ( mode == Mode.CLIENT ) - { - cipher.init( Cipher.ENCRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); - } - else - { - cipher.init( Cipher.DECRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); - } - } - catch ( final Exception e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - return cipher; - } - - - private void advanceMessageSequence() throws NTLMEngineException - { - if ( !isConnection ) - { - final MessageDigest sealMd5 = getMD5(); - sealMd5.update( sealingKey ); - final byte[] seqNumBytes = new byte[4]; - writeULong( seqNumBytes, sequenceNumber, 0 ); - sealMd5.update( seqNumBytes ); - sealingKey = sealMd5.digest(); - initCipher(); - } - sequenceNumber++; - } - - private byte[] encrypt( final byte[] data ) throws NTLMEngineException - { - return rc4.update( data ); - } - - private byte[] decrypt( final byte[] data ) throws NTLMEngineException - { - return rc4.update( data ); - } - - private byte[] computeSignature( final byte[] message ) throws NTLMEngineException - { - final byte[] sig = new byte[16]; - - // version - sig[0] = 0x01; - sig[1] = 0x00; - sig[2] = 0x00; - sig[3] = 0x00; - - // HMAC (first 8 bytes) - final HMACMD5 hmacMD5 = new HMACMD5( signingKey ); - hmacMD5.update( encodeLong( sequenceNumber ) ); - hmacMD5.update( message ); - final byte[] hmac = hmacMD5.getOutput(); - final byte[] trimmedHmac = new byte[8]; - System.arraycopy( hmac, 0, trimmedHmac, 0, 8 ); - final byte[] encryptedHmac = encrypt( trimmedHmac ); - System.arraycopy( encryptedHmac, 0, sig, 4, 8 ); - - // sequence number - encodeLong( sig, 12, sequenceNumber ); - - return sig; - } - - private boolean validateSignature( final byte[] signature, final byte message[] ) throws NTLMEngineException - { - final byte[] computedSignature = computeSignature( message ); - // log.info( "SSSSS validateSignature("+seqNumber+")\n" - // + " received: " + DebugUtil.dump( signature ) + "\n" - // + " computed: " + DebugUtil.dump( computedSignature ) ); - return Arrays.equals( signature, computedSignature ); - } - - public byte[] signAndEncryptMessage( final byte[] cleartextMessage ) throws NTLMEngineException - { - final byte[] encryptedMessage = encrypt( cleartextMessage ); - final byte[] signature = computeSignature( cleartextMessage ); - final byte[] outMessage = new byte[signature.length + encryptedMessage.length]; - System.arraycopy( signature, 0, outMessage, 0, signature.length ); - System.arraycopy( encryptedMessage, 0, outMessage, signature.length, encryptedMessage.length ); - advanceMessageSequence(); - return outMessage; - } - - public byte[] decryptAndVerifySignedMessage( final byte[] inMessage ) throws NTLMEngineException - { - final byte[] signature = new byte[16]; - System.arraycopy( inMessage, 0, signature, 0, signature.length ); - final byte[] encryptedMessage = new byte[inMessage.length - 16]; - System.arraycopy( inMessage, 16, encryptedMessage, 0, encryptedMessage.length ); - final byte[] cleartextMessage = decrypt( encryptedMessage ); - if ( !validateSignature( signature, cleartextMessage ) ) - { - throw new NTLMEngineException( "Wrong signature" ); - } - advanceMessageSequence(); - return cleartextMessage; - } - - } - - private static byte[] encodeLong( final int value ) - { - final byte[] enc = new byte[4]; - encodeLong( enc, 0, value ); - return enc; - } - - private static void encodeLong( final byte[] buf, final int offset, final int value ) - { - buf[offset + 0] = ( byte ) ( value & 0xff ); - buf[offset + 1] = ( byte ) ( value >> 8 & 0xff ); - buf[offset + 2] = ( byte ) ( value >> 16 & 0xff ); - buf[offset + 3] = ( byte ) ( value >> 24 & 0xff ); - } - - /** - * Creates the NTLMv2 blob from the given target information block and - * client challenge. - * - * @param targetInformation - * The target information block from the Type 2 message. - * @param clientChallenge - * The random 8-byte client challenge. - * - * @return The blob, used in the calculation of the NTLMv2 Response. - */ - private static byte[] createBlob(final byte[] clientChallenge, final byte[] targetInformation, final byte[] timestamp) { - final byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; - final byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - final byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8 - + unknown1.length + targetInformation.length + unknown2.length]; - int offset = 0; - System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); - offset += blobSignature.length; - System.arraycopy(reserved, 0, blob, offset, reserved.length); - offset += reserved.length; - System.arraycopy(timestamp, 0, blob, offset, timestamp.length); - offset += timestamp.length; - System.arraycopy(clientChallenge, 0, blob, offset, 8); - offset += 8; - System.arraycopy(unknown1, 0, blob, offset, unknown1.length); - offset += unknown1.length; - System.arraycopy(targetInformation, 0, blob, offset, targetInformation.length); - offset += targetInformation.length; - System.arraycopy(unknown2, 0, blob, offset, unknown2.length); - offset += unknown2.length; - return blob; - } - - /** - * Creates a DES encryption key from the given key material. - * - * @param bytes - * A byte array containing the DES key material. - * @param offset - * The offset in the given byte array at which the 7-byte key - * material starts. - * - * @return A DES encryption key created from the key material starting at - * the specified offset in the given byte array. - */ - private static Key createDESKey(final byte[] bytes, final int offset) { - final byte[] keyBytes = new byte[7]; - System.arraycopy(bytes, offset, keyBytes, 0, 7); - final byte[] material = new byte[8]; - material[0] = keyBytes[0]; - material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); - material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); - material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3); - material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4); - material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5); - material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6); - material[7] = (byte) (keyBytes[6] << 1); - oddParity(material); - return new SecretKeySpec(material, "DES"); - } - - /** - * Applies odd parity to the given byte array. - * - * @param bytes - * The data whose parity bits are to be adjusted for odd parity. - */ - private static void oddParity(final byte[] bytes) { - for (int i = 0; i < bytes.length; i++) { - final byte b = bytes[i]; - final boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) - ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0; - if (needsParity) { - bytes[i] |= (byte) 0x01; - } else { - bytes[i] &= (byte) 0xfe; - } - } - } - - /** - * Find the character set based on the flags. - * @param flags is the flags. - * @return the character set. - */ - private static Charset getCharset(final int flags) throws NTLMEngineException - { - if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { - return DEFAULT_CHARSET; - } else { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException( "Unicode not supported" ); - } - return UNICODE_LITTLE_UNMARKED; - } - } - - /** Strip dot suffix from a name */ - private static String stripDotSuffix(final String value) { - if (value == null) { - return null; - } - final int index = value.indexOf('.'); - if (index != -1) { - return value.substring(0, index); - } - return value; - } - - /** Convert host to standard form */ - private static String convertHost(final String host) { - return stripDotSuffix(host); - } - - /** Convert domain to standard form */ - private static String convertDomain(final String domain) { - return stripDotSuffix(domain); - } - - /** NTLM message generation, base class */ - static class NTLMMessage { - /** The current response */ - protected byte[] messageContents = null; - - /** The current output position */ - protected int currentOutputPosition = 0; - - /** Constructor to use when message contents are not yet known */ - NTLMMessage() { - } - - /** Constructor taking a string */ - NTLMMessage(final String messageBody, final int expectedType) throws NTLMEngineException { - this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET)), expectedType); - } - - /** Constructor to use when message bytes are known */ - NTLMMessage(final byte[] message, final int expectedType) throws NTLMEngineException { - messageContents = message; - // Look for NTLM message - if (messageContents.length < SIGNATURE.length) { - throw new NTLMEngineException("NTLM message decoding error - packet too short"); - } - int i = 0; - while (i < SIGNATURE.length) { - if (messageContents[i] != SIGNATURE[i]) { - throw new NTLMEngineException( - "NTLM message expected - instead got unrecognized bytes"); - } - i++; - } - - // Check to be sure there's a type 2 message indicator next - final int type = readULong(SIGNATURE.length); - if (type != expectedType) { - throw new NTLMEngineException("NTLM type " + Integer.toString(expectedType) - + " message expected - instead got type " + Integer.toString(type)); - } - - currentOutputPosition = messageContents.length; - } - - /** - * Get the length of the signature and flags, so calculations can adjust - * offsets accordingly. - */ - protected int getPreambleLength() { - return SIGNATURE.length + 4; - } - - /** Get the message length */ - protected int getMessageLength() { - return currentOutputPosition; - } - - /** Read a byte from a position within the message buffer */ - protected byte readByte(final int position) throws NTLMEngineException { - if (messageContents.length < position + 1) { - throw new NTLMEngineException("NTLM: Message too short"); - } - return messageContents[position]; - } - - /** Read a bunch of bytes from a position in the message buffer */ - protected void readBytes(final byte[] buffer, final int position) throws NTLMEngineException { - if (messageContents.length < position + buffer.length) { - throw new NTLMEngineException("NTLM: Message too short"); - } - System.arraycopy(messageContents, position, buffer, 0, buffer.length); - } - - /** Read a ushort from a position within the message buffer */ - protected int readUShort(final int position) throws NTLMEngineException { - return NTLMEngineImpl.readUShort(messageContents, position); - } - - /** Read a ulong from a position within the message buffer */ - protected int readULong(final int position) throws NTLMEngineException { - return NTLMEngineImpl.readULong(messageContents, position); - } - - /** Read a security buffer from a position within the message buffer */ - protected byte[] readSecurityBuffer(final int position) throws NTLMEngineException { - return NTLMEngineImpl.readSecurityBuffer(messageContents, position); - } - - /** - * Prepares the object to create a response of the given length. - * - * @param maxlength - * the maximum length of the response to prepare, - * including the type and the signature (which this method - * adds). - */ - protected void prepareResponse(final int maxlength, final int messageType) { - messageContents = new byte[maxlength]; - currentOutputPosition = 0; - addBytes(SIGNATURE); - addULong(messageType); - } - - /** - * Adds the given byte to the response. - * - * @param b - * the byte to add. - */ - protected void addByte(final byte b) { - messageContents[currentOutputPosition] = b; - currentOutputPosition++; - } - - /** - * Adds the given bytes to the response. - * - * @param bytes - * the bytes to add. - */ - protected void addBytes(final byte[] bytes) { - if (bytes == null) { - return; - } - for (final byte b : bytes) { - messageContents[currentOutputPosition] = b; - currentOutputPosition++; - } - } - - /** Adds a USHORT to the response */ - protected void addUShort(final int value) { - addByte((byte) (value & 0xff)); - addByte((byte) (value >> 8 & 0xff)); - } - - /** Adds a ULong to the response */ - protected void addULong(final int value) { - addByte((byte) (value & 0xff)); - addByte((byte) (value >> 8 & 0xff)); - addByte((byte) (value >> 16 & 0xff)); - addByte((byte) (value >> 24 & 0xff)); - } - - /** - * Returns the response that has been generated after shrinking the - * array if required and base64 encodes the response. - * - * @return The response as above. - */ - public String getResponse() { - return new String(Base64.encodeBase64(getBytes()), Consts.ASCII); - } - - public byte[] getBytes() { - if (messageContents == null) { - buildMessage(); - } - final byte[] resp; - if ( messageContents.length > currentOutputPosition ) { - final byte[] tmp = new byte[currentOutputPosition]; - System.arraycopy( messageContents, 0, tmp, 0, currentOutputPosition ); - messageContents = tmp; - } - return messageContents; - } - - protected void buildMessage() { - throw new RuntimeException("Message builder not implemented for "+getClass().getName()); - } - } - - /** Type 1 message assembly class */ - static class Type1Message extends NTLMMessage { - - private final byte[] hostBytes; - private final byte[] domainBytes; - private final int flags; - - Type1Message(final String domain, final String host) throws NTLMEngineException { - this(domain, host, null); - } - - Type1Message(final String domain, final String host, final Integer flags) throws NTLMEngineException { - super(); - this.flags = ((flags == null)?getDefaultFlags():flags); - - // Strip off domain name from the host! - final String unqualifiedHost = convertHost(host); - // Use only the base domain name! - final String unqualifiedDomain = convertDomain(domain); - - hostBytes = unqualifiedHost != null ? - unqualifiedHost.getBytes(UNICODE_LITTLE_UNMARKED) : null; - domainBytes = unqualifiedDomain != null ? - unqualifiedDomain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED) : null; - } - - Type1Message() { - super(); - hostBytes = null; - domainBytes = null; - flags = getDefaultFlags(); - } - - private int getDefaultFlags() { - return - //FLAG_WORKSTATION_PRESENT | - //FLAG_DOMAIN_PRESENT | - - // Required flags - //FLAG_REQUEST_LAN_MANAGER_KEY | - FLAG_REQUEST_NTLMv1 | - FLAG_REQUEST_NTLM2_SESSION | - - // Protocol version request - FLAG_REQUEST_VERSION | - - // Recommended privacy settings - FLAG_REQUEST_ALWAYS_SIGN | - //FLAG_REQUEST_SEAL | - //FLAG_REQUEST_SIGN | - - // These must be set according to documentation, based on use of SEAL above - FLAG_REQUEST_128BIT_KEY_EXCH | - FLAG_REQUEST_56BIT_ENCRYPTION | - //FLAG_REQUEST_EXPLICIT_KEY_EXCH | - - FLAG_REQUEST_UNICODE_ENCODING; - - } - - /** - * Getting the response involves building the message before returning - * it - */ - @Override - protected void buildMessage() { - int domainBytesLength = 0; - if ( domainBytes != null ) { - domainBytesLength = domainBytes.length; - } - int hostBytesLength = 0; - if ( hostBytes != null ) { - hostBytesLength = hostBytes.length; - } - - // Now, build the message. Calculate its length first, including - // signature or type. - final int finalLength = 32 + 8 + hostBytesLength + domainBytesLength; - - // Set up the response. This will initialize the signature, message - // type, and flags. - prepareResponse(finalLength, 1); - - // Flags. These are the complete set of flags we support. - addULong(flags); - - // Domain length (two times). - addUShort(domainBytesLength); - addUShort(domainBytesLength); - - // Domain offset. - addULong(hostBytesLength + 32 + 8); - - // Host length (two times). - addUShort(hostBytesLength); - addUShort(hostBytesLength); - - // Host offset (always 32 + 8). - addULong(32 + 8); - - // Version - addUShort(0x0105); - // Build - addULong(2600); - // NTLM revision - addUShort(0x0f00); - - // Host (workstation) String. - if (hostBytes != null) { - addBytes(hostBytes); - } - // Domain String. - if (domainBytes != null) { - addBytes(domainBytes); - } - } - - } - - /** Type 2 message class */ - static class Type2Message extends NTLMMessage { - protected final byte[] challenge; - protected String target; - protected byte[] targetInfo; - protected final int flags; - - Type2Message(final String messageBody) throws NTLMEngineException { - this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET))); - } - - Type2Message(final byte[] message) throws NTLMEngineException { - super(message, 2); - - // Type 2 message is laid out as follows: - // First 8 bytes: NTLMSSP[0] - // Next 4 bytes: Ulong, value 2 - // Next 8 bytes, starting at offset 12: target field (2 ushort lengths, 1 ulong offset) - // Next 4 bytes, starting at offset 20: Flags, e.g. 0x22890235 - // Next 8 bytes, starting at offset 24: Challenge - // Next 8 bytes, starting at offset 32: ??? (8 bytes of zeros) - // Next 8 bytes, starting at offset 40: targetinfo field (2 ushort lengths, 1 ulong offset) - // Next 2 bytes, major/minor version number (e.g. 0x05 0x02) - // Next 8 bytes, build number - // Next 2 bytes, protocol version number (e.g. 0x00 0x0f) - // Next, various text fields, and a ushort of value 0 at the end - - // Parse out the rest of the info we need from the message - // The nonce is the 8 bytes starting from the byte in position 24. - challenge = new byte[8]; - readBytes(challenge, 24); - - flags = readULong(20); - - // Do the target! - target = null; - // The TARGET_DESIRED flag is said to not have understood semantics - // in Type2 messages, so use the length of the packet to decide - // how to proceed instead - if (getMessageLength() >= 12 + 8) { - final byte[] bytes = readSecurityBuffer(12); - if (bytes.length != 0) { - target = new String(bytes, getCharset(flags)); - } - } - - // Do the target info! - targetInfo = null; - // TARGET_DESIRED flag cannot be relied on, so use packet length - if (getMessageLength() >= 40 + 8) { - final byte[] bytes = readSecurityBuffer(40); - if (bytes.length != 0) { - targetInfo = bytes; - } - } - } - - /** Retrieve the challenge */ - byte[] getChallenge() { - return challenge; - } - - /** Retrieve the target */ - String getTarget() { - return target; - } - - /** Retrieve the target info */ - byte[] getTargetInfo() { - return targetInfo; - } - - /** Retrieve the response flags */ - int getFlags() { - return flags; - } - - } - - /** Type 3 message assembly class */ - static class Type3Message extends NTLMMessage { - // For mic computation - protected final byte[] type1Message; - protected final byte[] type2Message; - // Response flags from the type2 message - protected final int type2Flags; - - protected final byte[] domainBytes; - protected final byte[] hostBytes; - protected final byte[] userBytes; - - protected byte[] lmResp; - protected byte[] ntResp; - protected final byte[] sessionKey; - protected final byte[] exportedSessionKey; - - protected final boolean computeMic; - - /** More primitive constructor: don't include cert or previous messages. - */ - Type3Message(final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation) - throws NTLMEngineException { - this(domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); - } - - /** More primitive constructor: don't include cert or previous messages. - */ - Type3Message(final Random random, final long currentTime, - final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation) - throws NTLMEngineException { - this(random, currentTime, domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); - } - - /** Constructor. Pass the arguments we will need */ - Type3Message(final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation, - final Certificate peerServerCertificate, - final byte[] type1Message, - final byte[] type2Message) - throws NTLMEngineException { - this(RND_GEN, System.currentTimeMillis(), domain, host, user, password, nonce, type2Flags, target, targetInformation, peerServerCertificate, type1Message, type2Message); - } - - /** Constructor. Pass the arguments we will need */ - Type3Message(final Random random, final long currentTime, - final String domain, - final String host, - final String user, - final String password, - final byte[] nonce, - final int type2Flags, - final String target, - final byte[] targetInformation, - final Certificate peerServerCertificate, - final byte[] type1Message, - final byte[] type2Message) - throws NTLMEngineException { - - if (random == null) { - throw new NTLMEngineException("Random generator not available"); - } - - // Save the flags - this.type2Flags = type2Flags; - this.type1Message = type1Message; - this.type2Message = type2Message; - - // Strip off domain name from the host! - final String unqualifiedHost = convertHost(host); - // Use only the base domain name! - final String unqualifiedDomain = convertDomain(domain); - - byte[] responseTargetInformation = targetInformation; - if (peerServerCertificate != null) { - responseTargetInformation = addGssMicAvsToTargetInfo(targetInformation, peerServerCertificate); - computeMic = true; - } else { - computeMic = false; - } - - // Create a cipher generator class. Use domain BEFORE it gets modified! - final CipherGen gen = new CipherGen(random, currentTime, - unqualifiedDomain, - user, - password, - nonce, - target, - responseTargetInformation); - - // Use the new code to calculate the responses, including v2 if that - // seems warranted. - byte[] userSessionKey; - try { - // This conditional may not work on Windows Server 2008 R2 and above, where it has not yet - // been tested - if (((type2Flags & FLAG_TARGETINFO_PRESENT) != 0) && - targetInformation != null && target != null) { - // NTLMv2 - ntResp = gen.getNTLMv2Response(); - lmResp = gen.getLMv2Response(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getNTLMv2UserSessionKey(); - } - } else { - // NTLMv1 - if ((type2Flags & FLAG_REQUEST_NTLM2_SESSION) != 0) { - // NTLM2 session stuff is requested - ntResp = gen.getNTLM2SessionResponse(); - lmResp = gen.getLM2SessionResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getNTLM2SessionResponseUserSessionKey(); - } - } else { - ntResp = gen.getNTLMResponse(); - lmResp = gen.getLMResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getNTLMUserSessionKey(); - } - } - } - } catch (final NTLMEngineException e) { - // This likely means we couldn't find the MD4 hash algorithm - - // fail back to just using LM - ntResp = new byte[0]; - lmResp = gen.getLMResponse(); - if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { - userSessionKey = gen.getLanManagerSessionKey(); - } else { - userSessionKey = gen.getLMUserSessionKey(); - } - } - - if ((type2Flags & FLAG_REQUEST_SIGN) != 0) { - if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) { - exportedSessionKey = gen.getSecondaryKey(); - sessionKey = RC4(exportedSessionKey, userSessionKey); - } else { - sessionKey = userSessionKey; - exportedSessionKey = sessionKey; - } - } else { - if (computeMic) { - throw new NTLMEngineException("Cannot sign/seal: no exported session key"); - } - sessionKey = null; - exportedSessionKey = null; - } - final Charset charset = getCharset(type2Flags); - hostBytes = unqualifiedHost != null ? unqualifiedHost.getBytes(charset) : null; - domainBytes = unqualifiedDomain != null ? unqualifiedDomain - .toUpperCase(Locale.ROOT).getBytes(charset) : null; - userBytes = user.getBytes(charset); - } - - public byte[] getEncryptedRandomSessionKey() { - return sessionKey; - } - - public byte[] getExportedSessionKey() { - return exportedSessionKey; - } - - /** Assemble the response */ - @Override - protected void buildMessage() { - final int ntRespLen = ntResp.length; - final int lmRespLen = lmResp.length; - - final int domainLen = domainBytes != null ? domainBytes.length : 0; - final int hostLen = hostBytes != null ? hostBytes.length: 0; - final int userLen = userBytes.length; - final int sessionKeyLen; - if (sessionKey != null) { - sessionKeyLen = sessionKey.length; - } else { - sessionKeyLen = 0; - } - - // Calculate the layout within the packet - final int lmRespOffset = 72 + // allocate space for the version - ( computeMic ? 16 : 0 ); // and MIC - final int ntRespOffset = lmRespOffset + lmRespLen; - final int domainOffset = ntRespOffset + ntRespLen; - final int userOffset = domainOffset + domainLen; - final int hostOffset = userOffset + userLen; - final int sessionKeyOffset = hostOffset + hostLen; - final int finalLength = sessionKeyOffset + sessionKeyLen; - - // Start the response. Length includes signature and type - prepareResponse(finalLength, 3); - - // LM Resp Length (twice) - addUShort(lmRespLen); - addUShort(lmRespLen); - - // LM Resp Offset - addULong(lmRespOffset); - - // NT Resp Length (twice) - addUShort(ntRespLen); - addUShort(ntRespLen); - - // NT Resp Offset - addULong(ntRespOffset); - - // Domain length (twice) - addUShort(domainLen); - addUShort(domainLen); - - // Domain offset. - addULong(domainOffset); - - // User Length (twice) - addUShort(userLen); - addUShort(userLen); - - // User offset - addULong(userOffset); - - // Host length (twice) - addUShort(hostLen); - addUShort(hostLen); - - // Host offset - addULong(hostOffset); - - // Session key length (twice) - addUShort(sessionKeyLen); - addUShort(sessionKeyLen); - - // Session key offset - addULong(sessionKeyOffset); - - // Flags. - addULong( - /* - //FLAG_WORKSTATION_PRESENT | - //FLAG_DOMAIN_PRESENT | - - // Required flags - (type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) | - (type2Flags & FLAG_REQUEST_NTLMv1) | - (type2Flags & FLAG_REQUEST_NTLM2_SESSION) | - - // Protocol version request - FLAG_REQUEST_VERSION | - - // Recommended privacy settings - (type2Flags & FLAG_REQUEST_ALWAYS_SIGN) | - (type2Flags & FLAG_REQUEST_SEAL) | - (type2Flags & FLAG_REQUEST_SIGN) | - - // These must be set according to documentation, based on use of SEAL above - (type2Flags & FLAG_REQUEST_128BIT_KEY_EXCH) | - (type2Flags & FLAG_REQUEST_56BIT_ENCRYPTION) | - (type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) | - - (type2Flags & FLAG_TARGETINFO_PRESENT) | - (type2Flags & FLAG_REQUEST_UNICODE_ENCODING) | - (type2Flags & FLAG_REQUEST_TARGET) - */ - type2Flags - ); - - // Version - addUShort(0x0105); - // Build - addULong(2600); - // NTLM revision - addUShort(0x0f00); - - int micPosition = -1; - if ( computeMic ) { - micPosition = currentOutputPosition; - currentOutputPosition += 16; - } - - // Add the actual data - addBytes(lmResp); - addBytes(ntResp); - addBytes(domainBytes); - addBytes(userBytes); - addBytes(hostBytes); - if (sessionKey != null) { - addBytes(sessionKey); - } - - // Write the mic back into its slot in the message - - if (computeMic) { - // Computation of message integrity code (MIC) as specified in [MS-NLMP] section 3.2.5.1.2. - final HMACMD5 hmacMD5 = new HMACMD5( exportedSessionKey ); - hmacMD5.update( type1Message ); - hmacMD5.update( type2Message ); - hmacMD5.update( messageContents ); - final byte[] mic = hmacMD5.getOutput(); - System.arraycopy( mic, 0, messageContents, micPosition, mic.length ); - } - } - - /** - * Add GSS channel binding hash and MIC flag to the targetInfo. - * Looks like this is needed if we want to use exported session key for GSS wrapping. - */ - private byte[] addGssMicAvsToTargetInfo( final byte[] originalTargetInfo, - final Certificate peerServerCertificate ) throws NTLMEngineException - { - final byte[] newTargetInfo = new byte[originalTargetInfo.length + 8 + 20]; - final int appendLength = originalTargetInfo.length - 4; // last tag is MSV_AV_EOL, do not copy that - System.arraycopy( originalTargetInfo, 0, newTargetInfo, 0, appendLength ); - writeUShort( newTargetInfo, MSV_AV_FLAGS, appendLength ); - writeUShort( newTargetInfo, 4, appendLength + 2 ); - writeULong( newTargetInfo, MSV_AV_FLAGS_MIC, appendLength + 4 ); - writeUShort( newTargetInfo, MSV_AV_CHANNEL_BINDINGS, appendLength + 8 ); - writeUShort( newTargetInfo, 16, appendLength + 10 ); - - final byte[] channelBindingsHash; - try - { - final byte[] certBytes = peerServerCertificate.getEncoded(); - final MessageDigest sha256 = MessageDigest.getInstance( "SHA-256" ); - final byte[] certHashBytes = sha256.digest( certBytes ); - final byte[] channelBindingStruct = new byte[16 + 4 + MAGIC_TLS_SERVER_ENDPOINT.length - + certHashBytes.length]; - writeULong( channelBindingStruct, 0x00000035, 16 ); - System.arraycopy( MAGIC_TLS_SERVER_ENDPOINT, 0, channelBindingStruct, 20, - MAGIC_TLS_SERVER_ENDPOINT.length ); - System.arraycopy( certHashBytes, 0, channelBindingStruct, 20 + MAGIC_TLS_SERVER_ENDPOINT.length, - certHashBytes.length ); - final MessageDigest md5 = getMD5(); - channelBindingsHash = md5.digest( channelBindingStruct ); - } - catch ( final CertificateEncodingException e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - catch ( final NoSuchAlgorithmException e ) - { - throw new NTLMEngineException( e.getMessage(), e ); - } - - System.arraycopy( channelBindingsHash, 0, newTargetInfo, appendLength + 12, 16 ); - return newTargetInfo; - } - - } - - static void writeUShort(final byte[] buffer, final int value, final int offset) { - buffer[offset] = ( byte ) ( value & 0xff ); - buffer[offset + 1] = ( byte ) ( value >> 8 & 0xff ); - } - - static void writeULong(final byte[] buffer, final int value, final int offset) { - buffer[offset] = (byte) (value & 0xff); - buffer[offset + 1] = (byte) (value >> 8 & 0xff); - buffer[offset + 2] = (byte) (value >> 16 & 0xff); - buffer[offset + 3] = (byte) (value >> 24 & 0xff); - } - - static int F(final int x, final int y, final int z) { - return ((x & y) | (~x & z)); - } - - static int G(final int x, final int y, final int z) { - return ((x & y) | (x & z) | (y & z)); - } - - static int H(final int x, final int y, final int z) { - return (x ^ y ^ z); - } - - static int rotintlft(final int val, final int numbits) { - return ((val << numbits) | (val >>> (32 - numbits))); - } - - static MessageDigest getMD5() { - try { - return MessageDigest.getInstance("MD5"); - } catch (final NoSuchAlgorithmException ex) { - throw new RuntimeException("MD5 message digest doesn't seem to exist - fatal error: "+ex.getMessage(), ex); - } - } - - /** - * Cryptography support - MD4. The following class was based loosely on the - * RFC and on code found at http://www.cs.umd.edu/~harry/jotp/src/md.java. - * Code correctness was verified by looking at MD4.java from the jcifs - * library (http://jcifs.samba.org). It was massaged extensively to the - * final form found here by Karl Wright (kwright@metacarta.com). - */ - static class MD4 { - protected int A = 0x67452301; - protected int B = 0xefcdab89; - protected int C = 0x98badcfe; - protected int D = 0x10325476; - protected long count = 0L; - protected final byte[] dataBuffer = new byte[64]; - - MD4() { - } - - void update(final byte[] input) { - // We always deal with 512 bits at a time. Correspondingly, there is - // a buffer 64 bytes long that we write data into until it gets - // full. - int curBufferPos = (int) (count & 63L); - int inputIndex = 0; - while (input.length - inputIndex + curBufferPos >= dataBuffer.length) { - // We have enough data to do the next step. Do a partial copy - // and a transform, updating inputIndex and curBufferPos - // accordingly - final int transferAmt = dataBuffer.length - curBufferPos; - System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); - count += transferAmt; - curBufferPos = 0; - inputIndex += transferAmt; - processBuffer(); - } - - // If there's anything left, copy it into the buffer and leave it. - // We know there's not enough left to process. - if (inputIndex < input.length) { - final int transferAmt = input.length - inputIndex; - System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); - count += transferAmt; - curBufferPos += transferAmt; - } - } - - byte[] getOutput() { - // Feed pad/length data into engine. This must round out the input - // to a multiple of 512 bits. - final int bufferIndex = (int) (count & 63L); - final int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); - final byte[] postBytes = new byte[padLen + 8]; - // Leading 0x80, specified amount of zero padding, then length in - // bits. - postBytes[0] = (byte) 0x80; - // Fill out the last 8 bytes with the length - for (int i = 0; i < 8; i++) { - postBytes[padLen + i] = (byte) ((count * 8) >>> (8 * i)); - } - - // Update the engine - update(postBytes); - - // Calculate final result - final byte[] result = new byte[16]; - writeULong(result, A, 0); - writeULong(result, B, 4); - writeULong(result, C, 8); - writeULong(result, D, 12); - return result; - } - - protected void processBuffer() { - // Convert current buffer to 16 ulongs - final int[] d = new int[16]; - - for (int i = 0; i < 16; i++) { - d[i] = (dataBuffer[i * 4] & 0xff) + ((dataBuffer[i * 4 + 1] & 0xff) << 8) - + ((dataBuffer[i * 4 + 2] & 0xff) << 16) - + ((dataBuffer[i * 4 + 3] & 0xff) << 24); - } - - // Do a round of processing - final int AA = A; - final int BB = B; - final int CC = C; - final int DD = D; - round1(d); - round2(d); - round3(d); - A += AA; - B += BB; - C += CC; - D += DD; - - } - - protected void round1(final int[] d) { - A = rotintlft((A + F(B, C, D) + d[0]), 3); - D = rotintlft((D + F(A, B, C) + d[1]), 7); - C = rotintlft((C + F(D, A, B) + d[2]), 11); - B = rotintlft((B + F(C, D, A) + d[3]), 19); - - A = rotintlft((A + F(B, C, D) + d[4]), 3); - D = rotintlft((D + F(A, B, C) + d[5]), 7); - C = rotintlft((C + F(D, A, B) + d[6]), 11); - B = rotintlft((B + F(C, D, A) + d[7]), 19); - - A = rotintlft((A + F(B, C, D) + d[8]), 3); - D = rotintlft((D + F(A, B, C) + d[9]), 7); - C = rotintlft((C + F(D, A, B) + d[10]), 11); - B = rotintlft((B + F(C, D, A) + d[11]), 19); - - A = rotintlft((A + F(B, C, D) + d[12]), 3); - D = rotintlft((D + F(A, B, C) + d[13]), 7); - C = rotintlft((C + F(D, A, B) + d[14]), 11); - B = rotintlft((B + F(C, D, A) + d[15]), 19); - } - - protected void round2(final int[] d) { - A = rotintlft((A + G(B, C, D) + d[0] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[4] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[8] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[12] + 0x5a827999), 13); - - A = rotintlft((A + G(B, C, D) + d[1] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[5] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[9] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[13] + 0x5a827999), 13); - - A = rotintlft((A + G(B, C, D) + d[2] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[6] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[10] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[14] + 0x5a827999), 13); - - A = rotintlft((A + G(B, C, D) + d[3] + 0x5a827999), 3); - D = rotintlft((D + G(A, B, C) + d[7] + 0x5a827999), 5); - C = rotintlft((C + G(D, A, B) + d[11] + 0x5a827999), 9); - B = rotintlft((B + G(C, D, A) + d[15] + 0x5a827999), 13); - - } - - protected void round3(final int[] d) { - A = rotintlft((A + H(B, C, D) + d[0] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[8] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[4] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[12] + 0x6ed9eba1), 15); - - A = rotintlft((A + H(B, C, D) + d[2] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[10] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[6] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[14] + 0x6ed9eba1), 15); - - A = rotintlft((A + H(B, C, D) + d[1] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[9] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[5] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[13] + 0x6ed9eba1), 15); - - A = rotintlft((A + H(B, C, D) + d[3] + 0x6ed9eba1), 3); - D = rotintlft((D + H(A, B, C) + d[11] + 0x6ed9eba1), 9); - C = rotintlft((C + H(D, A, B) + d[7] + 0x6ed9eba1), 11); - B = rotintlft((B + H(C, D, A) + d[15] + 0x6ed9eba1), 15); - - } - - } - - /** - * Cryptography support - HMACMD5 - algorithmically based on various web - * resources by Karl Wright - */ - static class HMACMD5 { - protected final byte[] ipad; - protected final byte[] opad; - protected final MessageDigest md5; - - HMACMD5(final byte[] input) { - byte[] key = input; - md5 = getMD5(); - - // Initialize the pad buffers with the key - ipad = new byte[64]; - opad = new byte[64]; - - int keyLength = key.length; - if (keyLength > 64) { - // Use MD5 of the key instead, as described in RFC 2104 - md5.update(key); - key = md5.digest(); - keyLength = key.length; - } - int i = 0; - while (i < keyLength) { - ipad[i] = (byte) (key[i] ^ (byte) 0x36); - opad[i] = (byte) (key[i] ^ (byte) 0x5c); - i++; - } - while (i < 64) { - ipad[i] = (byte) 0x36; - opad[i] = (byte) 0x5c; - i++; - } - - // Very important: processChallenge the digest with the ipad buffer - md5.reset(); - md5.update(ipad); - - } - - /** Grab the current digest. This is the "answer". */ - byte[] getOutput() { - final byte[] digest = md5.digest(); - md5.update(opad); - return md5.digest(digest); - } - - /** Update by adding a complete array */ - void update(final byte[] input) { - md5.update(input); - } - - /** Update the algorithm */ - void update(final byte[] input, final int offset, final int length) { - md5.update(input, offset, length); - } - - } - - @Override - public String generateType1Msg( - final String domain, - final String workstation) throws NTLMEngineException { - return getType1Message(workstation, domain); - } - - @Override - public String generateType3Msg( - final String username, - final String password, - final String domain, - final String workstation, - final String challenge) throws NTLMEngineException { - final Type2Message t2m = new Type2Message(challenge); - return getType3Message( - username, - password, - workstation, - domain, - t2m.getChallenge(), - t2m.getFlags(), - t2m.getTarget(), - t2m.getTargetInfo()); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.auth; + +import java.nio.charset.Charset; +import org.apache.http.Consts; +import java.security.Key; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Locale; +import java.util.Random; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.Certificate; + +import org.apache.commons.codec.binary.Base64; + +/** + * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM + * authentication protocol. + * + * @since 4.1 + */ +final class NTLMEngineImpl implements NTLMEngine { + + /** Unicode encoding */ + private static final Charset UNICODE_LITTLE_UNMARKED = Charset.forName("UnicodeLittleUnmarked"); + /** Character encoding */ + private static final Charset DEFAULT_CHARSET = Consts.ASCII; + + // Flags we use; descriptions according to: + // http://davenport.sourceforge.net/ntlm.html + // and + // http://msdn.microsoft.com/en-us/library/cc236650%28v=prot.20%29.aspx + // [MS-NLMP] section 2.2.2.5 + static final int FLAG_REQUEST_UNICODE_ENCODING = 0x00000001; // Unicode string encoding requested + static final int FLAG_REQUEST_OEM_ENCODING = 0x00000002; // OEM string encoding requested + static final int FLAG_REQUEST_TARGET = 0x00000004; // Requests target field + static final int FLAG_REQUEST_SIGN = 0x00000010; // Requests all messages have a signature attached, in NEGOTIATE message. + static final int FLAG_REQUEST_SEAL = 0x00000020; // Request key exchange for message confidentiality in NEGOTIATE message. MUST be used in conjunction with 56BIT. + static final int FLAG_REQUEST_LAN_MANAGER_KEY = 0x00000080; // Request Lan Manager key instead of user session key + static final int FLAG_REQUEST_NTLMv1 = 0x00000200; // Request NTLMv1 security. MUST be set in NEGOTIATE and CHALLENGE both + static final int FLAG_DOMAIN_PRESENT = 0x00001000; // Domain is present in message + static final int FLAG_WORKSTATION_PRESENT = 0x00002000; // Workstation is present in message + static final int FLAG_REQUEST_ALWAYS_SIGN = 0x00008000; // Requests a signature block on all messages. Overridden by REQUEST_SIGN and REQUEST_SEAL. + static final int FLAG_REQUEST_NTLM2_SESSION = 0x00080000; // From server in challenge, requesting NTLM2 session security + static final int FLAG_REQUEST_VERSION = 0x02000000; // Request protocol version + static final int FLAG_TARGETINFO_PRESENT = 0x00800000; // From server in challenge message, indicating targetinfo is present + static final int FLAG_REQUEST_128BIT_KEY_EXCH = 0x20000000; // Request explicit 128-bit key exchange + static final int FLAG_REQUEST_EXPLICIT_KEY_EXCH = 0x40000000; // Request explicit key exchange + static final int FLAG_REQUEST_56BIT_ENCRYPTION = 0x80000000; // Must be used in conjunction with SEAL + + // Attribute-value identifiers (AvId) + // according to [MS-NLMP] section 2.2.2.1 + static final int MSV_AV_EOL = 0x0000; // Indicates that this is the last AV_PAIR in the list. + static final int MSV_AV_NB_COMPUTER_NAME = 0x0001; // The server's NetBIOS computer name. + static final int MSV_AV_NB_DOMAIN_NAME = 0x0002; // The server's NetBIOS domain name. + static final int MSV_AV_DNS_COMPUTER_NAME = 0x0003; // The fully qualified domain name (FQDN) of the computer. + static final int MSV_AV_DNS_DOMAIN_NAME = 0x0004; // The FQDN of the domain. + static final int MSV_AV_DNS_TREE_NAME = 0x0005; // The FQDN of the forest. + static final int MSV_AV_FLAGS = 0x0006; // A 32-bit value indicating server or client configuration. + static final int MSV_AV_TIMESTAMP = 0x0007; // server local time + static final int MSV_AV_SINGLE_HOST = 0x0008; // A Single_Host_Data structure. + static final int MSV_AV_TARGET_NAME = 0x0009; // The SPN of the target server. + static final int MSV_AV_CHANNEL_BINDINGS = 0x000A; // A channel bindings hash. + + static final int MSV_AV_FLAGS_ACCOUNT_AUTH_CONSTAINED = 0x00000001; // Indicates to the client that the account authentication is constrained. + static final int MSV_AV_FLAGS_MIC = 0x00000002; // Indicates that the client is providing message integrity in the MIC field in the AUTHENTICATE_MESSAGE. + static final int MSV_AV_FLAGS_UNTRUSTED_TARGET_SPN = 0x00000004; // Indicates that the client is providing a target SPN generated from an untrusted source. + + /** Secure random generator */ + private static final java.security.SecureRandom RND_GEN; + static { + java.security.SecureRandom rnd = null; + try { + rnd = java.security.SecureRandom.getInstance("SHA1PRNG"); + } catch (final Exception ignore) { + } + RND_GEN = rnd; + } + + /** The signature string as bytes in the default encoding */ + private static final byte[] SIGNATURE = getNullTerminatedAsciiString("NTLMSSP"); + + // Key derivation magic strings for the SIGNKEY algorithm defined in + // [MS-NLMP] section 3.4.5.2 + private static final byte[] SIGN_MAGIC_SERVER = getNullTerminatedAsciiString( + "session key to server-to-client signing key magic constant"); + private static final byte[] SIGN_MAGIC_CLIENT = getNullTerminatedAsciiString( + "session key to client-to-server signing key magic constant"); + private static final byte[] SEAL_MAGIC_SERVER = getNullTerminatedAsciiString( + "session key to server-to-client sealing key magic constant"); + private static final byte[] SEAL_MAGIC_CLIENT = getNullTerminatedAsciiString( + "session key to client-to-server sealing key magic constant"); + + // prefix for GSS API channel binding + private static final byte[] MAGIC_TLS_SERVER_ENDPOINT = "tls-server-end-point:".getBytes(Consts.ASCII); + + private static byte[] getNullTerminatedAsciiString( final String source ) + { + final byte[] bytesWithoutNull = source.getBytes(Consts.ASCII); + final byte[] target = new byte[bytesWithoutNull.length + 1]; + System.arraycopy(bytesWithoutNull, 0, target, 0, bytesWithoutNull.length); + target[bytesWithoutNull.length] = (byte) 0x00; + return target; + } + + private static final String TYPE_1_MESSAGE = new Type1Message().getResponse(); + + NTLMEngineImpl() { + } + + /** + * Creates the first message (type 1 message) in the NTLM authentication + * sequence. This message includes the user name, domain and host for the + * authentication session. + * + * @param host + * the computer name of the host requesting authentication. + * @param domain + * The domain to authenticate with. + * @return String the message to add to the HTTP request header. + */ + static String getType1Message(final String host, final String domain) { + // For compatibility reason do not include domain and host in type 1 message + //return new Type1Message(domain, host).getResponse(); + return TYPE_1_MESSAGE; + } + + /** + * Creates the type 3 message using the given server nonce. The type 3 + * message includes all the information for authentication, host, domain, + * username and the result of encrypting the nonce sent by the server using + * the user's password as the key. + * + * @param user + * The user name. This should not include the domain name. + * @param password + * The password. + * @param host + * The host that is originating the authentication request. + * @param domain + * The domain to authenticate within. + * @param nonce + * the 8 byte array the server sent. + * @return The type 3 message. + * @throws NTLMEngineException + * If {@encrypt(byte[],byte[])} fails. + */ + static String getType3Message(final String user, final String password, final String host, final String domain, + final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation) + throws NTLMEngineException { + return new Type3Message(domain, host, user, password, nonce, type2Flags, target, + targetInformation).getResponse(); + } + + /** + * Creates the type 3 message using the given server nonce. The type 3 + * message includes all the information for authentication, host, domain, + * username and the result of encrypting the nonce sent by the server using + * the user's password as the key. + * + * @param user + * The user name. This should not include the domain name. + * @param password + * The password. + * @param host + * The host that is originating the authentication request. + * @param domain + * The domain to authenticate within. + * @param nonce + * the 8 byte array the server sent. + * @return The type 3 message. + * @throws NTLMEngineException + * If {@encrypt(byte[],byte[])} fails. + */ + static String getType3Message(final String user, final String password, final String host, final String domain, + final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation, + final Certificate peerServerCertificate, final byte[] type1Message, final byte[] type2Message) + throws NTLMEngineException { + return new Type3Message(domain, host, user, password, nonce, type2Flags, target, + targetInformation, peerServerCertificate, type1Message, type2Message).getResponse(); + } + + private static int readULong(final byte[] src, final int index) throws NTLMEngineException { + if (src.length < index + 4) { + return 0; + } + return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) + | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); + } + + private static int readUShort(final byte[] src, final int index) throws NTLMEngineException { + if (src.length < index + 2) { + return 0; + } + return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); + } + + private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException { + final int length = readUShort(src, index); + final int offset = readULong(src, index + 4); + if (src.length < offset + length) { + return new byte[length]; + } + final byte[] buffer = new byte[length]; + System.arraycopy(src, offset, buffer, 0, length); + return buffer; + } + + /** Calculate a challenge block */ + private static byte[] makeRandomChallenge(final Random random) throws NTLMEngineException { + final byte[] rval = new byte[8]; + synchronized (random) { + random.nextBytes(rval); + } + return rval; + } + + /** Calculate a 16-byte secondary key */ + private static byte[] makeSecondaryKey(final Random random) throws NTLMEngineException { + final byte[] rval = new byte[16]; + synchronized (random) { + random.nextBytes(rval); + } + return rval; + } + + protected static class CipherGen { + + protected final Random random; + protected final long currentTime; + + protected final String domain; + protected final String user; + protected final String password; + protected final byte[] challenge; + protected final String target; + protected final byte[] targetInformation; + + // Information we can generate but may be passed in (for testing) + protected byte[] clientChallenge; + protected byte[] clientChallenge2; + protected byte[] secondaryKey; + protected byte[] timestamp; + + // Stuff we always generate + protected byte[] lmHash = null; + protected byte[] lmResponse = null; + protected byte[] ntlmHash = null; + protected byte[] ntlmResponse = null; + protected byte[] ntlmv2Hash = null; + protected byte[] lmv2Hash = null; + protected byte[] lmv2Response = null; + protected byte[] ntlmv2Blob = null; + protected byte[] ntlmv2Response = null; + protected byte[] ntlm2SessionResponse = null; + protected byte[] lm2SessionResponse = null; + protected byte[] lmUserSessionKey = null; + protected byte[] ntlmUserSessionKey = null; + protected byte[] ntlmv2UserSessionKey = null; + protected byte[] ntlm2SessionResponseUserSessionKey = null; + protected byte[] lanManagerSessionKey = null; + + @Deprecated + public CipherGen(final String domain, final String user, final String password, + final byte[] challenge, final String target, final byte[] targetInformation, + final byte[] clientChallenge, final byte[] clientChallenge2, + final byte[] secondaryKey, final byte[] timestamp) { + this(RND_GEN, System.currentTimeMillis(), + domain, user, password, challenge, target, targetInformation, + clientChallenge, clientChallenge2, + secondaryKey, timestamp); + } + + public CipherGen(final Random random, final long currentTime, + final String domain, final String user, final String password, + final byte[] challenge, final String target, final byte[] targetInformation, + final byte[] clientChallenge, final byte[] clientChallenge2, + final byte[] secondaryKey, final byte[] timestamp) { + this.random = random; + this.currentTime = currentTime; + + this.domain = domain; + this.target = target; + this.user = user; + this.password = password; + this.challenge = challenge; + this.targetInformation = targetInformation; + this.clientChallenge = clientChallenge; + this.clientChallenge2 = clientChallenge2; + this.secondaryKey = secondaryKey; + this.timestamp = timestamp; + } + + @Deprecated + public CipherGen(final String domain, + final String user, + final String password, + final byte[] challenge, + final String target, + final byte[] targetInformation) { + this(RND_GEN, System.currentTimeMillis(), domain, user, password, challenge, target, targetInformation); + } + + public CipherGen(final Random random, final long currentTime, + final String domain, + final String user, + final String password, + final byte[] challenge, + final String target, + final byte[] targetInformation) { + this(random, currentTime, domain, user, password, challenge, target, targetInformation, null, null, null, null); + } + + /** Calculate and return client challenge */ + public byte[] getClientChallenge() + throws NTLMEngineException { + if (clientChallenge == null) { + clientChallenge = makeRandomChallenge(random); + } + return clientChallenge; + } + + /** Calculate and return second client challenge */ + public byte[] getClientChallenge2() + throws NTLMEngineException { + if (clientChallenge2 == null) { + clientChallenge2 = makeRandomChallenge(random); + } + return clientChallenge2; + } + + /** Calculate and return random secondary key */ + public byte[] getSecondaryKey() + throws NTLMEngineException { + if (secondaryKey == null) { + secondaryKey = makeSecondaryKey(random); + } + return secondaryKey; + } + + /** Calculate and return the LMHash */ + public byte[] getLMHash() + throws NTLMEngineException { + if (lmHash == null) { + lmHash = lmHash(password); + } + return lmHash; + } + + /** Calculate and return the LMResponse */ + public byte[] getLMResponse() + throws NTLMEngineException { + if (lmResponse == null) { + lmResponse = lmResponse(getLMHash(),challenge); + } + return lmResponse; + } + + /** Calculate and return the NTLMHash */ + public byte[] getNTLMHash() + throws NTLMEngineException { + if (ntlmHash == null) { + ntlmHash = ntlmHash(password); + } + return ntlmHash; + } + + /** Calculate and return the NTLMResponse */ + public byte[] getNTLMResponse() + throws NTLMEngineException { + if (ntlmResponse == null) { + ntlmResponse = lmResponse(getNTLMHash(),challenge); + } + return ntlmResponse; + } + + /** Calculate the LMv2 hash */ + public byte[] getLMv2Hash() + throws NTLMEngineException { + if (lmv2Hash == null) { + lmv2Hash = lmv2Hash(domain, user, getNTLMHash()); + } + return lmv2Hash; + } + + /** Calculate the NTLMv2 hash */ + public byte[] getNTLMv2Hash() + throws NTLMEngineException { + if (ntlmv2Hash == null) { + ntlmv2Hash = ntlmv2Hash(domain, user, getNTLMHash()); + } + return ntlmv2Hash; + } + + /** Calculate a timestamp */ + public byte[] getTimestamp() { + if (timestamp == null) { + long time = this.currentTime; + time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch. + time *= 10000; // tenths of a microsecond. + // convert to little-endian byte array. + timestamp = new byte[8]; + for (int i = 0; i < 8; i++) { + timestamp[i] = (byte) time; + time >>>= 8; + } + } + return timestamp; + } + + /** Calculate the NTLMv2Blob */ + public byte[] getNTLMv2Blob() + throws NTLMEngineException { + if (ntlmv2Blob == null) { + ntlmv2Blob = createBlob(getClientChallenge2(), targetInformation, getTimestamp()); + } + return ntlmv2Blob; + } + + /** Calculate the NTLMv2Response */ + public byte[] getNTLMv2Response() + throws NTLMEngineException { + if (ntlmv2Response == null) { + ntlmv2Response = lmv2Response(getNTLMv2Hash(),challenge,getNTLMv2Blob()); + } + return ntlmv2Response; + } + + /** Calculate the LMv2Response */ + public byte[] getLMv2Response() + throws NTLMEngineException { + if (lmv2Response == null) { + lmv2Response = lmv2Response(getLMv2Hash(),challenge,getClientChallenge()); + } + return lmv2Response; + } + + /** Get NTLM2SessionResponse */ + public byte[] getNTLM2SessionResponse() + throws NTLMEngineException { + if (ntlm2SessionResponse == null) { + ntlm2SessionResponse = ntlm2SessionResponse(getNTLMHash(),challenge,getClientChallenge()); + } + return ntlm2SessionResponse; + } + + /** Calculate and return LM2 session response */ + public byte[] getLM2SessionResponse() + throws NTLMEngineException { + if (lm2SessionResponse == null) { + final byte[] clntChallenge = getClientChallenge(); + lm2SessionResponse = new byte[24]; + System.arraycopy(clntChallenge, 0, lm2SessionResponse, 0, clntChallenge.length); + Arrays.fill(lm2SessionResponse, clntChallenge.length, lm2SessionResponse.length, (byte) 0x00); + } + return lm2SessionResponse; + } + + /** Get LMUserSessionKey */ + public byte[] getLMUserSessionKey() + throws NTLMEngineException { + if (lmUserSessionKey == null) { + lmUserSessionKey = new byte[16]; + System.arraycopy(getLMHash(), 0, lmUserSessionKey, 0, 8); + Arrays.fill(lmUserSessionKey, 8, 16, (byte) 0x00); + } + return lmUserSessionKey; + } + + /** Get NTLMUserSessionKey */ + public byte[] getNTLMUserSessionKey() + throws NTLMEngineException { + if (ntlmUserSessionKey == null) { + final MD4 md4 = new MD4(); + md4.update(getNTLMHash()); + ntlmUserSessionKey = md4.getOutput(); + } + return ntlmUserSessionKey; + } + + /** GetNTLMv2UserSessionKey */ + public byte[] getNTLMv2UserSessionKey() + throws NTLMEngineException { + if (ntlmv2UserSessionKey == null) { + final byte[] ntlmv2hash = getNTLMv2Hash(); + final byte[] truncatedResponse = new byte[16]; + System.arraycopy(getNTLMv2Response(), 0, truncatedResponse, 0, 16); + ntlmv2UserSessionKey = hmacMD5(truncatedResponse, ntlmv2hash); + } + return ntlmv2UserSessionKey; + } + + /** Get NTLM2SessionResponseUserSessionKey */ + public byte[] getNTLM2SessionResponseUserSessionKey() + throws NTLMEngineException { + if (ntlm2SessionResponseUserSessionKey == null) { + final byte[] ntlm2SessionResponseNonce = getLM2SessionResponse(); + final byte[] sessionNonce = new byte[challenge.length + ntlm2SessionResponseNonce.length]; + System.arraycopy(challenge, 0, sessionNonce, 0, challenge.length); + System.arraycopy(ntlm2SessionResponseNonce, 0, sessionNonce, challenge.length, ntlm2SessionResponseNonce.length); + ntlm2SessionResponseUserSessionKey = hmacMD5(sessionNonce,getNTLMUserSessionKey()); + } + return ntlm2SessionResponseUserSessionKey; + } + + /** Get LAN Manager session key */ + public byte[] getLanManagerSessionKey() + throws NTLMEngineException { + if (lanManagerSessionKey == null) { + try { + final byte[] keyBytes = new byte[14]; + System.arraycopy(getLMHash(), 0, keyBytes, 0, 8); + Arrays.fill(keyBytes, 8, keyBytes.length, (byte)0xbd); + final Key lowKey = createDESKey(keyBytes, 0); + final Key highKey = createDESKey(keyBytes, 7); + final byte[] truncatedResponse = new byte[8]; + System.arraycopy(getLMResponse(), 0, truncatedResponse, 0, truncatedResponse.length); + Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, lowKey); + final byte[] lowPart = des.doFinal(truncatedResponse); + des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, highKey); + final byte[] highPart = des.doFinal(truncatedResponse); + lanManagerSessionKey = new byte[16]; + System.arraycopy(lowPart, 0, lanManagerSessionKey, 0, lowPart.length); + System.arraycopy(highPart, 0, lanManagerSessionKey, lowPart.length, highPart.length); + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + return lanManagerSessionKey; + } + } + + /** Calculates HMAC-MD5 */ + static byte[] hmacMD5(final byte[] value, final byte[] key) + throws NTLMEngineException { + final HMACMD5 hmacMD5 = new HMACMD5(key); + hmacMD5.update(value); + return hmacMD5.getOutput(); + } + + /** Calculates RC4 */ + static byte[] RC4(final byte[] value, final byte[] key) + throws NTLMEngineException { + try { + final Cipher rc4 = Cipher.getInstance("RC4"); + rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC4")); + return rc4.doFinal(value); + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Calculates the NTLM2 Session Response for the given challenge, using the + * specified password and client challenge. + * + * @return The NTLM2 Session Response. This is placed in the NTLM response + * field of the Type 3 message; the LM response field contains the + * client challenge, null-padded to 24 bytes. + */ + static byte[] ntlm2SessionResponse(final byte[] ntlmHash, final byte[] challenge, + final byte[] clientChallenge) throws NTLMEngineException { + try { + final MessageDigest md5 = getMD5(); + md5.update(challenge); + md5.update(clientChallenge); + final byte[] digest = md5.digest(); + + final byte[] sessionHash = new byte[8]; + System.arraycopy(digest, 0, sessionHash, 0, 8); + return lmResponse(ntlmHash, sessionHash); + } catch (final Exception e) { + if (e instanceof NTLMEngineException) { + throw (NTLMEngineException) e; + } + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Creates the LM Hash of the user's password. + * + * @param password + * The password. + * + * @return The LM Hash of the given password, used in the calculation of the + * LM Response. + */ + private static byte[] lmHash(final String password) throws NTLMEngineException { + try { + final byte[] oemPassword = password.toUpperCase(Locale.ROOT).getBytes(Consts.ASCII); + final int length = Math.min(oemPassword.length, 14); + final byte[] keyBytes = new byte[14]; + System.arraycopy(oemPassword, 0, keyBytes, 0, length); + final Key lowKey = createDESKey(keyBytes, 0); + final Key highKey = createDESKey(keyBytes, 7); + final byte[] magicConstant = "KGS!@#$%".getBytes(Consts.ASCII); + final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, lowKey); + final byte[] lowHash = des.doFinal(magicConstant); + des.init(Cipher.ENCRYPT_MODE, highKey); + final byte[] highHash = des.doFinal(magicConstant); + final byte[] lmHash = new byte[16]; + System.arraycopy(lowHash, 0, lmHash, 0, 8); + System.arraycopy(highHash, 0, lmHash, 8, 8); + return lmHash; + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Creates the NTLM Hash of the user's password. + * + * @param password + * The password. + * + * @return The NTLM Hash of the given password, used in the calculation of + * the NTLM Response and the NTLMv2 and LMv2 Hashes. + */ + private static byte[] ntlmHash(final String password) throws NTLMEngineException { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException("Unicode not supported"); + } + final byte[] unicodePassword = password.getBytes(UNICODE_LITTLE_UNMARKED); + final MD4 md4 = new MD4(); + md4.update(unicodePassword); + return md4.getOutput(); + } + + /** + * Creates the LMv2 Hash of the user's password. + * + * @return The LMv2 Hash, used in the calculation of the NTLMv2 and LMv2 + * Responses. + */ + private static byte[] lmv2Hash(final String domain, final String user, final byte[] ntlmHash) + throws NTLMEngineException { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException("Unicode not supported"); + } + final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); + // Upper case username, upper case domain! + hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); + if (domain != null) { + hmacMD5.update(domain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); + } + return hmacMD5.getOutput(); + } + + /** + * Creates the NTLMv2 Hash of the user's password. + * + * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 and LMv2 + * Responses. + */ + private static byte[] ntlmv2Hash(final String domain, final String user, final byte[] ntlmHash) + throws NTLMEngineException { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException("Unicode not supported"); + } + final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); + // Upper case username, mixed case target!! + hmacMD5.update(user.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED)); + if (domain != null) { + hmacMD5.update(domain.getBytes(UNICODE_LITTLE_UNMARKED)); + } + return hmacMD5.getOutput(); + } + + /** + * Creates the LM Response from the given hash and Type 2 challenge. + * + * @param hash + * The LM or NTLM Hash. + * @param challenge + * The server challenge from the Type 2 message. + * + * @return The response (either LM or NTLM, depending on the provided hash). + */ + private static byte[] lmResponse(final byte[] hash, final byte[] challenge) throws NTLMEngineException { + try { + final byte[] keyBytes = new byte[21]; + System.arraycopy(hash, 0, keyBytes, 0, 16); + final Key lowKey = createDESKey(keyBytes, 0); + final Key middleKey = createDESKey(keyBytes, 7); + final Key highKey = createDESKey(keyBytes, 14); + final Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); + des.init(Cipher.ENCRYPT_MODE, lowKey); + final byte[] lowResponse = des.doFinal(challenge); + des.init(Cipher.ENCRYPT_MODE, middleKey); + final byte[] middleResponse = des.doFinal(challenge); + des.init(Cipher.ENCRYPT_MODE, highKey); + final byte[] highResponse = des.doFinal(challenge); + final byte[] lmResponse = new byte[24]; + System.arraycopy(lowResponse, 0, lmResponse, 0, 8); + System.arraycopy(middleResponse, 0, lmResponse, 8, 8); + System.arraycopy(highResponse, 0, lmResponse, 16, 8); + return lmResponse; + } catch (final Exception e) { + throw new NTLMEngineException(e.getMessage(), e); + } + } + + /** + * Creates the LMv2 Response from the given hash, client data, and Type 2 + * challenge. + * + * @param hash + * The NTLMv2 Hash. + * @param clientData + * The client data (blob or client challenge). + * @param challenge + * The server challenge from the Type 2 message. + * + * @return The response (either NTLMv2 or LMv2, depending on the client + * data). + */ + private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData) + throws NTLMEngineException { + final HMACMD5 hmacMD5 = new HMACMD5(hash); + hmacMD5.update(challenge); + hmacMD5.update(clientData); + final byte[] mac = hmacMD5.getOutput(); + final byte[] lmv2Response = new byte[mac.length + clientData.length]; + System.arraycopy(mac, 0, lmv2Response, 0, mac.length); + System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length); + return lmv2Response; + } + + static enum Mode + { + CLIENT, SERVER; + } + + static class Handle + { + final private byte[] exportedSessionKey; + private byte[] signingKey; + private byte[] sealingKey; + private final Cipher rc4; + final Mode mode; + final private boolean isConnection; + int sequenceNumber = 0; + + + Handle( final byte[] exportedSessionKey, final Mode mode, final boolean isConnection ) + throws NTLMEngineException + { + this.exportedSessionKey = exportedSessionKey; + this.isConnection = isConnection; + this.mode = mode; + try + { + final MessageDigest signMd5 = getMD5(); + final MessageDigest sealMd5 = getMD5(); + signMd5.update( exportedSessionKey ); + sealMd5.update( exportedSessionKey ); + if ( mode == Mode.CLIENT ) + { + signMd5.update( SIGN_MAGIC_CLIENT ); + sealMd5.update( SEAL_MAGIC_CLIENT ); + } + else + { + signMd5.update( SIGN_MAGIC_SERVER ); + sealMd5.update( SEAL_MAGIC_SERVER ); + } + signingKey = signMd5.digest(); + sealingKey = sealMd5.digest(); + } + catch ( final Exception e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + rc4 = initCipher(); + } + + public byte[] getSigningKey() + { + return signingKey; + } + + + public byte[] getSealingKey() + { + return sealingKey; + } + + private Cipher initCipher() throws NTLMEngineException + { + final Cipher cipher; + try + { + cipher = Cipher.getInstance( "RC4" ); + if ( mode == Mode.CLIENT ) + { + cipher.init( Cipher.ENCRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); + } + else + { + cipher.init( Cipher.DECRYPT_MODE, new SecretKeySpec( sealingKey, "RC4" ) ); + } + } + catch ( final Exception e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + return cipher; + } + + + private void advanceMessageSequence() throws NTLMEngineException + { + if ( !isConnection ) + { + final MessageDigest sealMd5 = getMD5(); + sealMd5.update( sealingKey ); + final byte[] seqNumBytes = new byte[4]; + writeULong( seqNumBytes, sequenceNumber, 0 ); + sealMd5.update( seqNumBytes ); + sealingKey = sealMd5.digest(); + initCipher(); + } + sequenceNumber++; + } + + private byte[] encrypt( final byte[] data ) throws NTLMEngineException + { + return rc4.update( data ); + } + + private byte[] decrypt( final byte[] data ) throws NTLMEngineException + { + return rc4.update( data ); + } + + private byte[] computeSignature( final byte[] message ) throws NTLMEngineException + { + final byte[] sig = new byte[16]; + + // version + sig[0] = 0x01; + sig[1] = 0x00; + sig[2] = 0x00; + sig[3] = 0x00; + + // HMAC (first 8 bytes) + final HMACMD5 hmacMD5 = new HMACMD5( signingKey ); + hmacMD5.update( encodeLong( sequenceNumber ) ); + hmacMD5.update( message ); + final byte[] hmac = hmacMD5.getOutput(); + final byte[] trimmedHmac = new byte[8]; + System.arraycopy( hmac, 0, trimmedHmac, 0, 8 ); + final byte[] encryptedHmac = encrypt( trimmedHmac ); + System.arraycopy( encryptedHmac, 0, sig, 4, 8 ); + + // sequence number + encodeLong( sig, 12, sequenceNumber ); + + return sig; + } + + private boolean validateSignature( final byte[] signature, final byte message[] ) throws NTLMEngineException + { + final byte[] computedSignature = computeSignature( message ); + // log.info( "SSSSS validateSignature("+seqNumber+")\n" + // + " received: " + DebugUtil.dump( signature ) + "\n" + // + " computed: " + DebugUtil.dump( computedSignature ) ); + return Arrays.equals( signature, computedSignature ); + } + + public byte[] signAndEncryptMessage( final byte[] cleartextMessage ) throws NTLMEngineException + { + final byte[] encryptedMessage = encrypt( cleartextMessage ); + final byte[] signature = computeSignature( cleartextMessage ); + final byte[] outMessage = new byte[signature.length + encryptedMessage.length]; + System.arraycopy( signature, 0, outMessage, 0, signature.length ); + System.arraycopy( encryptedMessage, 0, outMessage, signature.length, encryptedMessage.length ); + advanceMessageSequence(); + return outMessage; + } + + public byte[] decryptAndVerifySignedMessage( final byte[] inMessage ) throws NTLMEngineException + { + final byte[] signature = new byte[16]; + System.arraycopy( inMessage, 0, signature, 0, signature.length ); + final byte[] encryptedMessage = new byte[inMessage.length - 16]; + System.arraycopy( inMessage, 16, encryptedMessage, 0, encryptedMessage.length ); + final byte[] cleartextMessage = decrypt( encryptedMessage ); + if ( !validateSignature( signature, cleartextMessage ) ) + { + throw new NTLMEngineException( "Wrong signature" ); + } + advanceMessageSequence(); + return cleartextMessage; + } + + } + + private static byte[] encodeLong( final int value ) + { + final byte[] enc = new byte[4]; + encodeLong( enc, 0, value ); + return enc; + } + + private static void encodeLong( final byte[] buf, final int offset, final int value ) + { + buf[offset + 0] = ( byte ) ( value & 0xff ); + buf[offset + 1] = ( byte ) ( value >> 8 & 0xff ); + buf[offset + 2] = ( byte ) ( value >> 16 & 0xff ); + buf[offset + 3] = ( byte ) ( value >> 24 & 0xff ); + } + + /** + * Creates the NTLMv2 blob from the given target information block and + * client challenge. + * + * @param targetInformation + * The target information block from the Type 2 message. + * @param clientChallenge + * The random 8-byte client challenge. + * + * @return The blob, used in the calculation of the NTLMv2 Response. + */ + private static byte[] createBlob(final byte[] clientChallenge, final byte[] targetInformation, final byte[] timestamp) { + final byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; + final byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + final byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + final byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + final byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8 + + unknown1.length + targetInformation.length + unknown2.length]; + int offset = 0; + System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); + offset += blobSignature.length; + System.arraycopy(reserved, 0, blob, offset, reserved.length); + offset += reserved.length; + System.arraycopy(timestamp, 0, blob, offset, timestamp.length); + offset += timestamp.length; + System.arraycopy(clientChallenge, 0, blob, offset, 8); + offset += 8; + System.arraycopy(unknown1, 0, blob, offset, unknown1.length); + offset += unknown1.length; + System.arraycopy(targetInformation, 0, blob, offset, targetInformation.length); + offset += targetInformation.length; + System.arraycopy(unknown2, 0, blob, offset, unknown2.length); + offset += unknown2.length; + return blob; + } + + /** + * Creates a DES encryption key from the given key material. + * + * @param bytes + * A byte array containing the DES key material. + * @param offset + * The offset in the given byte array at which the 7-byte key + * material starts. + * + * @return A DES encryption key created from the key material starting at + * the specified offset in the given byte array. + */ + private static Key createDESKey(final byte[] bytes, final int offset) { + final byte[] keyBytes = new byte[7]; + System.arraycopy(bytes, offset, keyBytes, 0, 7); + final byte[] material = new byte[8]; + material[0] = keyBytes[0]; + material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); + material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); + material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3); + material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4); + material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5); + material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6); + material[7] = (byte) (keyBytes[6] << 1); + oddParity(material); + return new SecretKeySpec(material, "DES"); + } + + /** + * Applies odd parity to the given byte array. + * + * @param bytes + * The data whose parity bits are to be adjusted for odd parity. + */ + private static void oddParity(final byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + final byte b = bytes[i]; + final boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) + ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0; + if (needsParity) { + bytes[i] |= (byte) 0x01; + } else { + bytes[i] &= (byte) 0xfe; + } + } + } + + /** + * Find the character set based on the flags. + * @param flags is the flags. + * @return the character set. + */ + private static Charset getCharset(final int flags) throws NTLMEngineException + { + if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { + return DEFAULT_CHARSET; + } else { + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException( "Unicode not supported" ); + } + return UNICODE_LITTLE_UNMARKED; + } + } + + /** Strip dot suffix from a name */ + private static String stripDotSuffix(final String value) { + if (value == null) { + return null; + } + final int index = value.indexOf('.'); + if (index != -1) { + return value.substring(0, index); + } + return value; + } + + /** Convert host to standard form */ + private static String convertHost(final String host) { + return stripDotSuffix(host); + } + + /** Convert domain to standard form */ + private static String convertDomain(final String domain) { + return stripDotSuffix(domain); + } + + /** NTLM message generation, base class */ + static class NTLMMessage { + /** The current response */ + protected byte[] messageContents = null; + + /** The current output position */ + protected int currentOutputPosition = 0; + + /** Constructor to use when message contents are not yet known */ + NTLMMessage() { + } + + /** Constructor taking a string */ + NTLMMessage(final String messageBody, final int expectedType) throws NTLMEngineException { + this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET)), expectedType); + } + + /** Constructor to use when message bytes are known */ + NTLMMessage(final byte[] message, final int expectedType) throws NTLMEngineException { + messageContents = message; + // Look for NTLM message + if (messageContents.length < SIGNATURE.length) { + throw new NTLMEngineException("NTLM message decoding error - packet too short"); + } + int i = 0; + while (i < SIGNATURE.length) { + if (messageContents[i] != SIGNATURE[i]) { + throw new NTLMEngineException( + "NTLM message expected - instead got unrecognized bytes"); + } + i++; + } + + // Check to be sure there's a type 2 message indicator next + final int type = readULong(SIGNATURE.length); + if (type != expectedType) { + throw new NTLMEngineException("NTLM type " + Integer.toString(expectedType) + + " message expected - instead got type " + Integer.toString(type)); + } + + currentOutputPosition = messageContents.length; + } + + /** + * Get the length of the signature and flags, so calculations can adjust + * offsets accordingly. + */ + protected int getPreambleLength() { + return SIGNATURE.length + 4; + } + + /** Get the message length */ + protected int getMessageLength() { + return currentOutputPosition; + } + + /** Read a byte from a position within the message buffer */ + protected byte readByte(final int position) throws NTLMEngineException { + if (messageContents.length < position + 1) { + throw new NTLMEngineException("NTLM: Message too short"); + } + return messageContents[position]; + } + + /** Read a bunch of bytes from a position in the message buffer */ + protected void readBytes(final byte[] buffer, final int position) throws NTLMEngineException { + if (messageContents.length < position + buffer.length) { + throw new NTLMEngineException("NTLM: Message too short"); + } + System.arraycopy(messageContents, position, buffer, 0, buffer.length); + } + + /** Read a ushort from a position within the message buffer */ + protected int readUShort(final int position) throws NTLMEngineException { + return NTLMEngineImpl.readUShort(messageContents, position); + } + + /** Read a ulong from a position within the message buffer */ + protected int readULong(final int position) throws NTLMEngineException { + return NTLMEngineImpl.readULong(messageContents, position); + } + + /** Read a security buffer from a position within the message buffer */ + protected byte[] readSecurityBuffer(final int position) throws NTLMEngineException { + return NTLMEngineImpl.readSecurityBuffer(messageContents, position); + } + + /** + * Prepares the object to create a response of the given length. + * + * @param maxlength + * the maximum length of the response to prepare, + * including the type and the signature (which this method + * adds). + */ + protected void prepareResponse(final int maxlength, final int messageType) { + messageContents = new byte[maxlength]; + currentOutputPosition = 0; + addBytes(SIGNATURE); + addULong(messageType); + } + + /** + * Adds the given byte to the response. + * + * @param b + * the byte to add. + */ + protected void addByte(final byte b) { + messageContents[currentOutputPosition] = b; + currentOutputPosition++; + } + + /** + * Adds the given bytes to the response. + * + * @param bytes + * the bytes to add. + */ + protected void addBytes(final byte[] bytes) { + if (bytes == null) { + return; + } + for (final byte b : bytes) { + messageContents[currentOutputPosition] = b; + currentOutputPosition++; + } + } + + /** Adds a USHORT to the response */ + protected void addUShort(final int value) { + addByte((byte) (value & 0xff)); + addByte((byte) (value >> 8 & 0xff)); + } + + /** Adds a ULong to the response */ + protected void addULong(final int value) { + addByte((byte) (value & 0xff)); + addByte((byte) (value >> 8 & 0xff)); + addByte((byte) (value >> 16 & 0xff)); + addByte((byte) (value >> 24 & 0xff)); + } + + /** + * Returns the response that has been generated after shrinking the + * array if required and base64 encodes the response. + * + * @return The response as above. + */ + public String getResponse() { + return new String(Base64.encodeBase64(getBytes()), Consts.ASCII); + } + + public byte[] getBytes() { + if (messageContents == null) { + buildMessage(); + } + final byte[] resp; + if ( messageContents.length > currentOutputPosition ) { + final byte[] tmp = new byte[currentOutputPosition]; + System.arraycopy( messageContents, 0, tmp, 0, currentOutputPosition ); + messageContents = tmp; + } + return messageContents; + } + + protected void buildMessage() { + throw new RuntimeException("Message builder not implemented for "+getClass().getName()); + } + } + + /** Type 1 message assembly class */ + static class Type1Message extends NTLMMessage { + + private final byte[] hostBytes; + private final byte[] domainBytes; + private final int flags; + + Type1Message(final String domain, final String host) throws NTLMEngineException { + this(domain, host, null); + } + + Type1Message(final String domain, final String host, final Integer flags) throws NTLMEngineException { + super(); + this.flags = ((flags == null)?getDefaultFlags():flags); + + // Strip off domain name from the host! + final String unqualifiedHost = convertHost(host); + // Use only the base domain name! + final String unqualifiedDomain = convertDomain(domain); + + hostBytes = unqualifiedHost != null ? + unqualifiedHost.getBytes(UNICODE_LITTLE_UNMARKED) : null; + domainBytes = unqualifiedDomain != null ? + unqualifiedDomain.toUpperCase(Locale.ROOT).getBytes(UNICODE_LITTLE_UNMARKED) : null; + } + + Type1Message() { + super(); + hostBytes = null; + domainBytes = null; + flags = getDefaultFlags(); + } + + private int getDefaultFlags() { + return + //FLAG_WORKSTATION_PRESENT | + //FLAG_DOMAIN_PRESENT | + + // Required flags + //FLAG_REQUEST_LAN_MANAGER_KEY | + FLAG_REQUEST_NTLMv1 | + FLAG_REQUEST_NTLM2_SESSION | + + // Protocol version request + FLAG_REQUEST_VERSION | + + // Recommended privacy settings + FLAG_REQUEST_ALWAYS_SIGN | + //FLAG_REQUEST_SEAL | + //FLAG_REQUEST_SIGN | + + // These must be set according to documentation, based on use of SEAL above + FLAG_REQUEST_128BIT_KEY_EXCH | + FLAG_REQUEST_56BIT_ENCRYPTION | + //FLAG_REQUEST_EXPLICIT_KEY_EXCH | + + FLAG_REQUEST_UNICODE_ENCODING; + + } + + /** + * Getting the response involves building the message before returning + * it + */ + @Override + protected void buildMessage() { + int domainBytesLength = 0; + if ( domainBytes != null ) { + domainBytesLength = domainBytes.length; + } + int hostBytesLength = 0; + if ( hostBytes != null ) { + hostBytesLength = hostBytes.length; + } + + // Now, build the message. Calculate its length first, including + // signature or type. + final int finalLength = 32 + 8 + hostBytesLength + domainBytesLength; + + // Set up the response. This will initialize the signature, message + // type, and flags. + prepareResponse(finalLength, 1); + + // Flags. These are the complete set of flags we support. + addULong(flags); + + // Domain length (two times). + addUShort(domainBytesLength); + addUShort(domainBytesLength); + + // Domain offset. + addULong(hostBytesLength + 32 + 8); + + // Host length (two times). + addUShort(hostBytesLength); + addUShort(hostBytesLength); + + // Host offset (always 32 + 8). + addULong(32 + 8); + + // Version + addUShort(0x0105); + // Build + addULong(2600); + // NTLM revision + addUShort(0x0f00); + + // Host (workstation) String. + if (hostBytes != null) { + addBytes(hostBytes); + } + // Domain String. + if (domainBytes != null) { + addBytes(domainBytes); + } + } + + } + + /** Type 2 message class */ + static class Type2Message extends NTLMMessage { + protected final byte[] challenge; + protected String target; + protected byte[] targetInfo; + protected final int flags; + + Type2Message(final String messageBody) throws NTLMEngineException { + this(Base64.decodeBase64(messageBody.getBytes(DEFAULT_CHARSET))); + } + + Type2Message(final byte[] message) throws NTLMEngineException { + super(message, 2); + + // Type 2 message is laid out as follows: + // First 8 bytes: NTLMSSP[0] + // Next 4 bytes: Ulong, value 2 + // Next 8 bytes, starting at offset 12: target field (2 ushort lengths, 1 ulong offset) + // Next 4 bytes, starting at offset 20: Flags, e.g. 0x22890235 + // Next 8 bytes, starting at offset 24: Challenge + // Next 8 bytes, starting at offset 32: ??? (8 bytes of zeros) + // Next 8 bytes, starting at offset 40: targetinfo field (2 ushort lengths, 1 ulong offset) + // Next 2 bytes, major/minor version number (e.g. 0x05 0x02) + // Next 8 bytes, build number + // Next 2 bytes, protocol version number (e.g. 0x00 0x0f) + // Next, various text fields, and a ushort of value 0 at the end + + // Parse out the rest of the info we need from the message + // The nonce is the 8 bytes starting from the byte in position 24. + challenge = new byte[8]; + readBytes(challenge, 24); + + flags = readULong(20); + + // Do the target! + target = null; + // The TARGET_DESIRED flag is said to not have understood semantics + // in Type2 messages, so use the length of the packet to decide + // how to proceed instead + if (getMessageLength() >= 12 + 8) { + final byte[] bytes = readSecurityBuffer(12); + if (bytes.length != 0) { + target = new String(bytes, getCharset(flags)); + } + } + + // Do the target info! + targetInfo = null; + // TARGET_DESIRED flag cannot be relied on, so use packet length + if (getMessageLength() >= 40 + 8) { + final byte[] bytes = readSecurityBuffer(40); + if (bytes.length != 0) { + targetInfo = bytes; + } + } + } + + /** Retrieve the challenge */ + byte[] getChallenge() { + return challenge; + } + + /** Retrieve the target */ + String getTarget() { + return target; + } + + /** Retrieve the target info */ + byte[] getTargetInfo() { + return targetInfo; + } + + /** Retrieve the response flags */ + int getFlags() { + return flags; + } + + } + + /** Type 3 message assembly class */ + static class Type3Message extends NTLMMessage { + // For mic computation + protected final byte[] type1Message; + protected final byte[] type2Message; + // Response flags from the type2 message + protected final int type2Flags; + + protected final byte[] domainBytes; + protected final byte[] hostBytes; + protected final byte[] userBytes; + + protected byte[] lmResp; + protected byte[] ntResp; + protected final byte[] sessionKey; + protected final byte[] exportedSessionKey; + + protected final boolean computeMic; + + /** More primitive constructor: don't include cert or previous messages. + */ + Type3Message(final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation) + throws NTLMEngineException { + this(domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); + } + + /** More primitive constructor: don't include cert or previous messages. + */ + Type3Message(final Random random, final long currentTime, + final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation) + throws NTLMEngineException { + this(random, currentTime, domain, host, user, password, nonce, type2Flags, target, targetInformation, null, null, null); + } + + /** Constructor. Pass the arguments we will need */ + Type3Message(final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation, + final Certificate peerServerCertificate, + final byte[] type1Message, + final byte[] type2Message) + throws NTLMEngineException { + this(RND_GEN, System.currentTimeMillis(), domain, host, user, password, nonce, type2Flags, target, targetInformation, peerServerCertificate, type1Message, type2Message); + } + + /** Constructor. Pass the arguments we will need */ + Type3Message(final Random random, final long currentTime, + final String domain, + final String host, + final String user, + final String password, + final byte[] nonce, + final int type2Flags, + final String target, + final byte[] targetInformation, + final Certificate peerServerCertificate, + final byte[] type1Message, + final byte[] type2Message) + throws NTLMEngineException { + + if (random == null) { + throw new NTLMEngineException("Random generator not available"); + } + + // Save the flags + this.type2Flags = type2Flags; + this.type1Message = type1Message; + this.type2Message = type2Message; + + // Strip off domain name from the host! + final String unqualifiedHost = convertHost(host); + // Use only the base domain name! + final String unqualifiedDomain = convertDomain(domain); + + byte[] responseTargetInformation = targetInformation; + if (peerServerCertificate != null) { + responseTargetInformation = addGssMicAvsToTargetInfo(targetInformation, peerServerCertificate); + computeMic = true; + } else { + computeMic = false; + } + + // Create a cipher generator class. Use domain BEFORE it gets modified! + final CipherGen gen = new CipherGen(random, currentTime, + unqualifiedDomain, + user, + password, + nonce, + target, + responseTargetInformation); + + // Use the new code to calculate the responses, including v2 if that + // seems warranted. + byte[] userSessionKey; + try { + // This conditional may not work on Windows Server 2008 R2 and above, where it has not yet + // been tested + if (((type2Flags & FLAG_TARGETINFO_PRESENT) != 0) && + targetInformation != null && target != null) { + // NTLMv2 + ntResp = gen.getNTLMv2Response(); + lmResp = gen.getLMv2Response(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getNTLMv2UserSessionKey(); + } + } else { + // NTLMv1 + if ((type2Flags & FLAG_REQUEST_NTLM2_SESSION) != 0) { + // NTLM2 session stuff is requested + ntResp = gen.getNTLM2SessionResponse(); + lmResp = gen.getLM2SessionResponse(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getNTLM2SessionResponseUserSessionKey(); + } + } else { + ntResp = gen.getNTLMResponse(); + lmResp = gen.getLMResponse(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getNTLMUserSessionKey(); + } + } + } + } catch (final NTLMEngineException e) { + // This likely means we couldn't find the MD4 hash algorithm - + // fail back to just using LM + ntResp = new byte[0]; + lmResp = gen.getLMResponse(); + if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) { + userSessionKey = gen.getLanManagerSessionKey(); + } else { + userSessionKey = gen.getLMUserSessionKey(); + } + } + + if ((type2Flags & FLAG_REQUEST_SIGN) != 0) { + if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) { + exportedSessionKey = gen.getSecondaryKey(); + sessionKey = RC4(exportedSessionKey, userSessionKey); + } else { + sessionKey = userSessionKey; + exportedSessionKey = sessionKey; + } + } else { + if (computeMic) { + throw new NTLMEngineException("Cannot sign/seal: no exported session key"); + } + sessionKey = null; + exportedSessionKey = null; + } + final Charset charset = getCharset(type2Flags); + hostBytes = unqualifiedHost != null ? unqualifiedHost.getBytes(charset) : null; + domainBytes = unqualifiedDomain != null ? unqualifiedDomain + .toUpperCase(Locale.ROOT).getBytes(charset) : null; + userBytes = user.getBytes(charset); + } + + public byte[] getEncryptedRandomSessionKey() { + return sessionKey; + } + + public byte[] getExportedSessionKey() { + return exportedSessionKey; + } + + /** Assemble the response */ + @Override + protected void buildMessage() { + final int ntRespLen = ntResp.length; + final int lmRespLen = lmResp.length; + + final int domainLen = domainBytes != null ? domainBytes.length : 0; + final int hostLen = hostBytes != null ? hostBytes.length: 0; + final int userLen = userBytes.length; + final int sessionKeyLen; + if (sessionKey != null) { + sessionKeyLen = sessionKey.length; + } else { + sessionKeyLen = 0; + } + + // Calculate the layout within the packet + final int lmRespOffset = 72 + // allocate space for the version + ( computeMic ? 16 : 0 ); // and MIC + final int ntRespOffset = lmRespOffset + lmRespLen; + final int domainOffset = ntRespOffset + ntRespLen; + final int userOffset = domainOffset + domainLen; + final int hostOffset = userOffset + userLen; + final int sessionKeyOffset = hostOffset + hostLen; + final int finalLength = sessionKeyOffset + sessionKeyLen; + + // Start the response. Length includes signature and type + prepareResponse(finalLength, 3); + + // LM Resp Length (twice) + addUShort(lmRespLen); + addUShort(lmRespLen); + + // LM Resp Offset + addULong(lmRespOffset); + + // NT Resp Length (twice) + addUShort(ntRespLen); + addUShort(ntRespLen); + + // NT Resp Offset + addULong(ntRespOffset); + + // Domain length (twice) + addUShort(domainLen); + addUShort(domainLen); + + // Domain offset. + addULong(domainOffset); + + // User Length (twice) + addUShort(userLen); + addUShort(userLen); + + // User offset + addULong(userOffset); + + // Host length (twice) + addUShort(hostLen); + addUShort(hostLen); + + // Host offset + addULong(hostOffset); + + // Session key length (twice) + addUShort(sessionKeyLen); + addUShort(sessionKeyLen); + + // Session key offset + addULong(sessionKeyOffset); + + // Flags. + addULong( + /* + //FLAG_WORKSTATION_PRESENT | + //FLAG_DOMAIN_PRESENT | + + // Required flags + (type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) | + (type2Flags & FLAG_REQUEST_NTLMv1) | + (type2Flags & FLAG_REQUEST_NTLM2_SESSION) | + + // Protocol version request + FLAG_REQUEST_VERSION | + + // Recommended privacy settings + (type2Flags & FLAG_REQUEST_ALWAYS_SIGN) | + (type2Flags & FLAG_REQUEST_SEAL) | + (type2Flags & FLAG_REQUEST_SIGN) | + + // These must be set according to documentation, based on use of SEAL above + (type2Flags & FLAG_REQUEST_128BIT_KEY_EXCH) | + (type2Flags & FLAG_REQUEST_56BIT_ENCRYPTION) | + (type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) | + + (type2Flags & FLAG_TARGETINFO_PRESENT) | + (type2Flags & FLAG_REQUEST_UNICODE_ENCODING) | + (type2Flags & FLAG_REQUEST_TARGET) + */ + type2Flags + ); + + // Version + addUShort(0x0105); + // Build + addULong(2600); + // NTLM revision + addUShort(0x0f00); + + int micPosition = -1; + if ( computeMic ) { + micPosition = currentOutputPosition; + currentOutputPosition += 16; + } + + // Add the actual data + addBytes(lmResp); + addBytes(ntResp); + addBytes(domainBytes); + addBytes(userBytes); + addBytes(hostBytes); + if (sessionKey != null) { + addBytes(sessionKey); + } + + // Write the mic back into its slot in the message + + if (computeMic) { + // Computation of message integrity code (MIC) as specified in [MS-NLMP] section 3.2.5.1.2. + final HMACMD5 hmacMD5 = new HMACMD5( exportedSessionKey ); + hmacMD5.update( type1Message ); + hmacMD5.update( type2Message ); + hmacMD5.update( messageContents ); + final byte[] mic = hmacMD5.getOutput(); + System.arraycopy( mic, 0, messageContents, micPosition, mic.length ); + } + } + + /** + * Add GSS channel binding hash and MIC flag to the targetInfo. + * Looks like this is needed if we want to use exported session key for GSS wrapping. + */ + private byte[] addGssMicAvsToTargetInfo( final byte[] originalTargetInfo, + final Certificate peerServerCertificate ) throws NTLMEngineException + { + final byte[] newTargetInfo = new byte[originalTargetInfo.length + 8 + 20]; + final int appendLength = originalTargetInfo.length - 4; // last tag is MSV_AV_EOL, do not copy that + System.arraycopy( originalTargetInfo, 0, newTargetInfo, 0, appendLength ); + writeUShort( newTargetInfo, MSV_AV_FLAGS, appendLength ); + writeUShort( newTargetInfo, 4, appendLength + 2 ); + writeULong( newTargetInfo, MSV_AV_FLAGS_MIC, appendLength + 4 ); + writeUShort( newTargetInfo, MSV_AV_CHANNEL_BINDINGS, appendLength + 8 ); + writeUShort( newTargetInfo, 16, appendLength + 10 ); + + final byte[] channelBindingsHash; + try + { + final byte[] certBytes = peerServerCertificate.getEncoded(); + final MessageDigest sha256 = MessageDigest.getInstance( "SHA-256" ); + final byte[] certHashBytes = sha256.digest( certBytes ); + final byte[] channelBindingStruct = new byte[16 + 4 + MAGIC_TLS_SERVER_ENDPOINT.length + + certHashBytes.length]; + writeULong( channelBindingStruct, 0x00000035, 16 ); + System.arraycopy( MAGIC_TLS_SERVER_ENDPOINT, 0, channelBindingStruct, 20, + MAGIC_TLS_SERVER_ENDPOINT.length ); + System.arraycopy( certHashBytes, 0, channelBindingStruct, 20 + MAGIC_TLS_SERVER_ENDPOINT.length, + certHashBytes.length ); + final MessageDigest md5 = getMD5(); + channelBindingsHash = md5.digest( channelBindingStruct ); + } + catch ( final CertificateEncodingException e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + catch ( final NoSuchAlgorithmException e ) + { + throw new NTLMEngineException( e.getMessage(), e ); + } + + System.arraycopy( channelBindingsHash, 0, newTargetInfo, appendLength + 12, 16 ); + return newTargetInfo; + } + + } + + static void writeUShort(final byte[] buffer, final int value, final int offset) { + buffer[offset] = ( byte ) ( value & 0xff ); + buffer[offset + 1] = ( byte ) ( value >> 8 & 0xff ); + } + + static void writeULong(final byte[] buffer, final int value, final int offset) { + buffer[offset] = (byte) (value & 0xff); + buffer[offset + 1] = (byte) (value >> 8 & 0xff); + buffer[offset + 2] = (byte) (value >> 16 & 0xff); + buffer[offset + 3] = (byte) (value >> 24 & 0xff); + } + + static int F(final int x, final int y, final int z) { + return ((x & y) | (~x & z)); + } + + static int G(final int x, final int y, final int z) { + return ((x & y) | (x & z) | (y & z)); + } + + static int H(final int x, final int y, final int z) { + return (x ^ y ^ z); + } + + static int rotintlft(final int val, final int numbits) { + return ((val << numbits) | (val >>> (32 - numbits))); + } + + static MessageDigest getMD5() { + try { + return MessageDigest.getInstance("MD5"); + } catch (final NoSuchAlgorithmException ex) { + throw new RuntimeException("MD5 message digest doesn't seem to exist - fatal error: "+ex.getMessage(), ex); + } + } + + /** + * Cryptography support - MD4. The following class was based loosely on the + * RFC and on code found at http://www.cs.umd.edu/~harry/jotp/src/md.java. + * Code correctness was verified by looking at MD4.java from the jcifs + * library (http://jcifs.samba.org). It was massaged extensively to the + * final form found here by Karl Wright (kwright@metacarta.com). + */ + static class MD4 { + protected int A = 0x67452301; + protected int B = 0xefcdab89; + protected int C = 0x98badcfe; + protected int D = 0x10325476; + protected long count = 0L; + protected final byte[] dataBuffer = new byte[64]; + + MD4() { + } + + void update(final byte[] input) { + // We always deal with 512 bits at a time. Correspondingly, there is + // a buffer 64 bytes long that we write data into until it gets + // full. + int curBufferPos = (int) (count & 63L); + int inputIndex = 0; + while (input.length - inputIndex + curBufferPos >= dataBuffer.length) { + // We have enough data to do the next step. Do a partial copy + // and a transform, updating inputIndex and curBufferPos + // accordingly + final int transferAmt = dataBuffer.length - curBufferPos; + System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); + count += transferAmt; + curBufferPos = 0; + inputIndex += transferAmt; + processBuffer(); + } + + // If there's anything left, copy it into the buffer and leave it. + // We know there's not enough left to process. + if (inputIndex < input.length) { + final int transferAmt = input.length - inputIndex; + System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); + count += transferAmt; + curBufferPos += transferAmt; + } + } + + byte[] getOutput() { + // Feed pad/length data into engine. This must round out the input + // to a multiple of 512 bits. + final int bufferIndex = (int) (count & 63L); + final int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); + final byte[] postBytes = new byte[padLen + 8]; + // Leading 0x80, specified amount of zero padding, then length in + // bits. + postBytes[0] = (byte) 0x80; + // Fill out the last 8 bytes with the length + for (int i = 0; i < 8; i++) { + postBytes[padLen + i] = (byte) ((count * 8) >>> (8 * i)); + } + + // Update the engine + update(postBytes); + + // Calculate final result + final byte[] result = new byte[16]; + writeULong(result, A, 0); + writeULong(result, B, 4); + writeULong(result, C, 8); + writeULong(result, D, 12); + return result; + } + + protected void processBuffer() { + // Convert current buffer to 16 ulongs + final int[] d = new int[16]; + + for (int i = 0; i < 16; i++) { + d[i] = (dataBuffer[i * 4] & 0xff) + ((dataBuffer[i * 4 + 1] & 0xff) << 8) + + ((dataBuffer[i * 4 + 2] & 0xff) << 16) + + ((dataBuffer[i * 4 + 3] & 0xff) << 24); + } + + // Do a round of processing + final int AA = A; + final int BB = B; + final int CC = C; + final int DD = D; + round1(d); + round2(d); + round3(d); + A += AA; + B += BB; + C += CC; + D += DD; + + } + + protected void round1(final int[] d) { + A = rotintlft((A + F(B, C, D) + d[0]), 3); + D = rotintlft((D + F(A, B, C) + d[1]), 7); + C = rotintlft((C + F(D, A, B) + d[2]), 11); + B = rotintlft((B + F(C, D, A) + d[3]), 19); + + A = rotintlft((A + F(B, C, D) + d[4]), 3); + D = rotintlft((D + F(A, B, C) + d[5]), 7); + C = rotintlft((C + F(D, A, B) + d[6]), 11); + B = rotintlft((B + F(C, D, A) + d[7]), 19); + + A = rotintlft((A + F(B, C, D) + d[8]), 3); + D = rotintlft((D + F(A, B, C) + d[9]), 7); + C = rotintlft((C + F(D, A, B) + d[10]), 11); + B = rotintlft((B + F(C, D, A) + d[11]), 19); + + A = rotintlft((A + F(B, C, D) + d[12]), 3); + D = rotintlft((D + F(A, B, C) + d[13]), 7); + C = rotintlft((C + F(D, A, B) + d[14]), 11); + B = rotintlft((B + F(C, D, A) + d[15]), 19); + } + + protected void round2(final int[] d) { + A = rotintlft((A + G(B, C, D) + d[0] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[4] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[8] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[12] + 0x5a827999), 13); + + A = rotintlft((A + G(B, C, D) + d[1] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[5] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[9] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[13] + 0x5a827999), 13); + + A = rotintlft((A + G(B, C, D) + d[2] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[6] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[10] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[14] + 0x5a827999), 13); + + A = rotintlft((A + G(B, C, D) + d[3] + 0x5a827999), 3); + D = rotintlft((D + G(A, B, C) + d[7] + 0x5a827999), 5); + C = rotintlft((C + G(D, A, B) + d[11] + 0x5a827999), 9); + B = rotintlft((B + G(C, D, A) + d[15] + 0x5a827999), 13); + + } + + protected void round3(final int[] d) { + A = rotintlft((A + H(B, C, D) + d[0] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[8] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[4] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[12] + 0x6ed9eba1), 15); + + A = rotintlft((A + H(B, C, D) + d[2] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[10] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[6] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[14] + 0x6ed9eba1), 15); + + A = rotintlft((A + H(B, C, D) + d[1] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[9] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[5] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[13] + 0x6ed9eba1), 15); + + A = rotintlft((A + H(B, C, D) + d[3] + 0x6ed9eba1), 3); + D = rotintlft((D + H(A, B, C) + d[11] + 0x6ed9eba1), 9); + C = rotintlft((C + H(D, A, B) + d[7] + 0x6ed9eba1), 11); + B = rotintlft((B + H(C, D, A) + d[15] + 0x6ed9eba1), 15); + + } + + } + + /** + * Cryptography support - HMACMD5 - algorithmically based on various web + * resources by Karl Wright + */ + static class HMACMD5 { + protected final byte[] ipad; + protected final byte[] opad; + protected final MessageDigest md5; + + HMACMD5(final byte[] input) { + byte[] key = input; + md5 = getMD5(); + + // Initialize the pad buffers with the key + ipad = new byte[64]; + opad = new byte[64]; + + int keyLength = key.length; + if (keyLength > 64) { + // Use MD5 of the key instead, as described in RFC 2104 + md5.update(key); + key = md5.digest(); + keyLength = key.length; + } + int i = 0; + while (i < keyLength) { + ipad[i] = (byte) (key[i] ^ (byte) 0x36); + opad[i] = (byte) (key[i] ^ (byte) 0x5c); + i++; + } + while (i < 64) { + ipad[i] = (byte) 0x36; + opad[i] = (byte) 0x5c; + i++; + } + + // Very important: processChallenge the digest with the ipad buffer + md5.reset(); + md5.update(ipad); + + } + + /** Grab the current digest. This is the "answer". */ + byte[] getOutput() { + final byte[] digest = md5.digest(); + md5.update(opad); + return md5.digest(digest); + } + + /** Update by adding a complete array */ + void update(final byte[] input) { + md5.update(input); + } + + /** Update the algorithm */ + void update(final byte[] input, final int offset, final int length) { + md5.update(input, offset, length); + } + + } + + @Override + public String generateType1Msg( + final String domain, + final String workstation) throws NTLMEngineException { + return getType1Message(workstation, domain); + } + + @Override + public String generateType3Msg( + final String username, + final String password, + final String domain, + final String workstation, + final String challenge) throws NTLMEngineException { + final Type2Message t2m = new Type2Message(challenge); + return getType3Message( + username, + password, + workstation, + domain, + t2m.getChallenge(), + t2m.getFlags(), + t2m.getTarget(), + t2m.getTargetInfo()); + } + +} diff --git a/httpmime/pom.xml b/httpmime/pom.xml index e9ccca7a46..ba07fa233e 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.5 + 4.5.6-SNAPSHOT httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 354fef9661..03183c2b11 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.5 + 4.5.6-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 @@ -61,7 +61,7 @@ scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 4.5.5 + 4.5.6-SNAPSHOT From 97b5055cc1b377a3b7b2013f96589fa7b28ffb59 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 27 Jan 2018 10:17:53 +0100 Subject: [PATCH 178/204] HTTPCLIENT-1900: proxy protocol processor does not post-process CONNECT response messages --- .../main/java/org/apache/http/impl/execchain/MainClientExec.java | 1 + 1 file changed, 1 insertion(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java index a932a08c1d..579ffedde2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java @@ -471,6 +471,7 @@ private boolean createTunnelToTarget( this.authenticator.generateAuthResponse(connect, proxyAuthState, context); response = this.requestExecutor.execute(connect, managedConn, context); + this.requestExecutor.postProcess(response, this.proxyHttpProcessor, context); final int status = response.getStatusLine().getStatusCode(); if (status < 200) { From c215bc7bb5f1aae9387c420c5b668ec3c5830b05 Mon Sep 17 00:00:00 2001 From: Hans-Peter Keck Date: Fri, 9 Feb 2018 10:21:59 +0100 Subject: [PATCH 179/204] HTTPCLIENT-1904: check cookie domain for null --- .../org/apache/http/impl/cookie/PublicSuffixDomainFilter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java index 24d37283ce..47c30075ab 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java @@ -90,6 +90,9 @@ public PublicSuffixDomainFilter( @Override public boolean match(final Cookie cookie, final CookieOrigin origin) { final String host = cookie.getDomain(); + if (host == null) { + return false; + } final int i = host.indexOf('.'); if (i >= 0) { final String domain = host.substring(i); From b1e09f37ae6e11bbca12b2296f29e603c1a9d22b Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 26 Feb 2018 15:08:23 +0100 Subject: [PATCH 180/204] HTTPCLIENT-1906: certificates containing alternative subject names other than DNS and IP (such as RFC822) get rejected as invalid --- .../conn/ssl/DefaultHostnameVerifier.java | 12 +++++---- .../http/conn/ssl/CertificatesToPlayWith.java | 25 +++++++++++++++++++ .../conn/ssl/TestDefaultHostnameVerifier.java | 4 +++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java index 2202abe16f..1453ba3b70 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/DefaultHostnameVerifier.java @@ -305,11 +305,13 @@ static List getSubjectAltNames(final X509Certificate cert) { for (final List entry : entries) { final Integer type = entry.size() >= 2 ? (Integer) entry.get(0) : null; if (type != null) { - final Object o = entry.get(1); - if (o instanceof String) { - result.add(new SubjectName((String) o, type.intValue())); - } else if (o instanceof byte[]) { - // TODO ASN.1 DER encoded form + if (type == SubjectName.DNS || type == SubjectName.IP) { + final Object o = entry.get(1); + if (o instanceof String) { + result.add(new SubjectName((String) o, type)); + } else if (o instanceof byte[]) { + // TODO ASN.1 DER encoded form + } } } } diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java b/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java index 284c111fab..99df26b335 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/CertificatesToPlayWith.java @@ -550,4 +550,29 @@ public class CertificatesToPlayWith { "-----END CERTIFICATE-----" ).getBytes(); + public final static byte[] EMAIL_ALT_SUBJECT_NAME = ( + "-----BEGIN CERTIFICATE-----\n" + + "MIIDpTCCAo2gAwIBAgIJANqkMEtlkelbMA0GCSqGSIb3DQEBCwUAMHAxCzAJBgNV\n" + + "BAYTAlVTMQswCQYDVQQIDAJWQTERMA8GA1UEBwwIU29tZUNpdHkxEjAQBgNVBAoM\n" + + "CU15Q29tcGFueTETMBEGA1UECwwKTXlEaXZpc2lvbjEYMBYGA1UEAwwPd3d3LmNv\n" + + "bXBhbnkuY29tMB4XDTE4MDIxNTA3MjkzMFoXDTIwMDIxNTA3MjkzMFowcDELMAkG\n" + + "A1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0eTESMBAGA1UE\n" + + "CgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRgwFgYDVQQDDA93d3cu\n" + + "Y29tcGFueS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4v6Oq\n" + + "Ua0goRVn1cmT7MOpJhXFm3A70bTpvJIRpEjtGIz99hb34/9r5AYyf1VhKyWmBq24\n" + + "XNcOJ59XOlyjjbm2Tl811ufTOdcNbPadoVBmMt4039OSUFpVb4wAw2XPWLTCG2h1\n" + + "HNj9GuFHmwcDsg5EiIRrhDGQm2LLLAGoe5PdReoMZCeeWzNWvKTCV14pyRzwQhJL\n" + + "F1OmzLYzovbPfB8LZVhQgDbLsh034FScivf2oKDB+NEzAEagNpnrFR0MFLWGYsu1\n" + + "nWD5RiZi78HFGiibmhH7QrEPfGlo2eofuUga6naoBUROqkmMCIL8n1HZ/Ur0oGny\n" + + "vQCj1AyrfOhuVC53AgMBAAGjQjBAMAsGA1UdDwQEAwIEMDATBgNVHSUEDDAKBggr\n" + + "BgEFBQcDATAcBgNVHREEFTATgRFlbWFpbEBleGFtcGxlLmNvbTANBgkqhkiG9w0B\n" + + "AQsFAAOCAQEAZ0IsqRrsEmJ6Fa9Yo6PQtrKJrejN2TTDddVgyLQdokzWh/25JFad\n" + + "NCMYPH5KjTUyKf96hJDlDayjbKk1PMMhSZMU5OG9NOuGMH/dQttruG1ojse7KIKg\n" + + "yHDQrfq5Exxgfa7CMHRKAoTCY7JZhSLyVbTMVhmGfuUDad/RA86ZisXycp0ZmS97\n" + + "qDkAmzFL0sL0ZUWNNUh4ZUWvCUZwiuN08z70NjGqXMTDCf68p3SYxbII0xTfScgf\n" + + "aQ/A/hD7IbGGTexeoTwpEj01DNvefbQV6//neo32/R5XD0D5jn3TCgZcMThA6H3a\n" + + "VkEghVg+s7uMfL/UEebOBQWXQJ/uVoknMA==\n" + + "-----END CERTIFICATE-----" + ).getBytes(); + } diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java b/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java index a58f468ee7..744c3ca4e7 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/TestDefaultHostnameVerifier.java @@ -164,6 +164,10 @@ public void testVerify() throws Exception { exceptionPlease(impl, "1.1.1.2", x509); exceptionPlease(impl, "dummy-value.com", x509); + + in = new ByteArrayInputStream(CertificatesToPlayWith.EMAIL_ALT_SUBJECT_NAME); + x509 = (X509Certificate) cf.generateCertificate(in); + impl.verify("www.company.com", x509); } @Test From 460b60607d7c423db04aa72665fcdc1e164fc1a0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 20 Mar 2018 17:50:56 -0600 Subject: [PATCH 181/204] [HTTPCLIENT-1911] Failing tests on Fedora 28 due to weak encryption algorithms in test keystore. --- RELEASE_NOTES.txt | 14 ++++++++++++++ .../src/test/resources/test-DSA-1024.keystore | Bin 0 -> 1344 bytes httpclient/src/test/resources/test.keystore | Bin 1344 -> 2181 bytes 3 files changed, 14 insertions(+) create mode 100644 httpclient/src/test/resources/test-DSA-1024.keystore diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index b4f3ea6bda..d2f7d363bc 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,17 @@ +Release 4.5.6 +------------------- + +HttpClient 4.5.6 (GA) is a maintenance release. + +Please note that as of 4.4 HttpClient requires Java 1.6 or newer. + +Changelog: +------------------- + +* [HTTPCLIENT-1911]: Failing tests on Fedora 28 due to weak encryption algorithms in test keystore. + Contributed by Gary Gregory and Michael Simacek + + Release 4.5.5 ------------------- diff --git a/httpclient/src/test/resources/test-DSA-1024.keystore b/httpclient/src/test/resources/test-DSA-1024.keystore new file mode 100644 index 0000000000000000000000000000000000000000..917f83ea7d47dad1a41fe46ff2582cdc4fcd4dd7 GIT binary patch literal 1344 zcmezO_TO6u1_mY|W&~rQ;>_HFoK)S6l9B@5;?$zD)FPmie$PwZ>p;5Spoy{DfRBw! zn~jl$QHx2Ck&%^wrHQfp)N!H413LsXN{ZXQ``uU?Ol=zhzh%HD7v+ePcNw3fbI zXEfDy{)q;0o*#)n8?w^3Hox7e9uB)H8kR(3*Wyk4Pq;2qx+KO16B z=!T1l=bQK%uzWnpaPxA@mv0}pSRD8rJRwN3PUglAk1ti*xwV(uOxSRTx7s?`*qzVf z>rW}WgcsY7Oj{Xk#jx^_OIJjIY%)u~hS8)qy;Ef`opN_kX4qC68@1!MlsW%`BYnSm zmNmvc`|)nc{jg<@$5iCE2VII+w(;Jte(_JnNz0>_H{(_;`F5(ZNWM|Tm_g2dUPegV z=I@gYT+c9ZGJi3-x%!@8^Pc_vM{Kow!!Pd@xa};me0Rh|zQ@-^;)JfLtME)+b}BsB zy#Dx|6Kh&y)5Kq}am@g(T9PX{W`8%^_-pSf=Vjn1V~x-= zHLzr0V2(3rVvYi0@deCGj7&@{zFVu647l0Ywc0$+S+Fp(G8i=W8wvoUk2#cuO_)72 zFFP;4JP#(qfg!?<5K%Tz1nJ@umU1jeOwLGE2+mI{DNig)RdCBM%}Yrv$;{6)lrxY4 zDdH9ug(~s@CL-tj+=BeP)Vz{nLm>kJkUX<6XHI@{VopYWafyMPIIp3hfr*i+p|OdX zp+OXwYi?u$em&~94 zf~8tO>5%{KmDm4mKPLUdI{f*u70X2VS$;QvyL?pcFq3JBaFp0Yqi?03*J&qS*Lwd+ ziCJ>)MGwZ~Ori|a69W20mATJsnzXZN(d!oO4-qn7K~DSra6#*}*|zsi?^zvVwj+FJ z<&^cie_6e1`Wf!SZOh)29vB(kx9duz|Fc4NfyRa{o??Z{FMKq_gtwpPH0n9A?4gZV zRd+~Duf~JL>*TaIFDspxx454Bm!fIX$KOd+j4IY=mVDf|B5*?Iist(dqn^%Zo79~a z*H9g*n!@N~{qMY|7IR|@15;yz>0+P0+f&ZU^(~yTZqkJ5(;fzVun(N4zm%cAvC`jr z?WVPjchZk>L~m7p`)D%VcVTMrD$hR?;qZEp8AdH*+A%{-4S)wO?4 b)xWi;ALp8_yfsJQWbmc~e~(4!EN}q;sl*hE literal 0 HcmV?d00001 diff --git a/httpclient/src/test/resources/test.keystore b/httpclient/src/test/resources/test.keystore index 917f83ea7d47dad1a41fe46ff2582cdc4fcd4dd7..8234a3d7d3dfbbf53f7320093c0d0a44337e9997 100644 GIT binary patch delta 2049 zcmZvcc{tMz0LS;+mMiqOn){7KM4N_T(~v8XE6kbuE=rW6WXv_va@1UTkaI+gl41=x za%9Poq8#O#nVco``m;aYKfnKczt8jeKF^0KkZ?Fnf#_*e$>IZn4uH@k=nh(#N8l6> z00or5hXLRK2ugy^yTB~AH8cXi(P_C|Z23&>1+i*H@pZBuQN?3h8huGEvb8e=;1eYbSW(jo6w3 zMwE#7VOyiUuGp=^72mSt5<7H<@WF0FmPi>rX=d%+LIK zqpF`9P~_E`k;eK2*1Bin2-YutCVNc6ifHDK)Bkr{4Ic8VTtxjrw_M-64?@eM@_~FT z=O|ez?6Q#CoP&vMq_6m+xhyQ-6QR`S$&YSo(e+@+Qg2*!#Ut&MqdyG{1zH1PGj6ZhjMx&U*Q&4OHD>$^bX#{(%m63vQNtOYo^EPCXYy5$IHPvNv>;_xK? zc&&S#(o6ZQOz_5c2dcE>SQq$R&tuOz3keQtrERZ3{vJ8OF0^Y*=KZ^dFIfT>TRO#G znQ@|dMs^byhYN17C5i6JMw%a?H%@qsvf{zlo}*$jTHz5t5p^X)aNQlaU3+m;Brz()3_xBlQ#F4a8_+`i z;`cH5Yh15E&n(tEAMcUhQ})`+K5d8pR``~H&o+t*>c(SEA92yfY-Dt@f1c{Hz+H*q z%W}&uIL zeHvVa9Qtf&vWHONWyqu?X{q3e~dnu|(is&O|kOSz)n_c;nOV@dWi1XUx z{qTFX`F6>iPw4J!rHtUY9B5uV7X$(UpaTxd>S!DY1W`qkAj)VGSfmgF2Ebsb zQ(fkJv=9%!QsVi-pj;ou#^%f| zaLMn^SH@96qpS0|*&n)$E%>B_zuvZ~oi;#lKjEpg0Q>r;m&2pmzrF$6E1bfsGLUoh zO{?C>NYA&uN&S*nBixZOR~Nr}+;O;AK)g`FmYgwbypgSCVwB0RY_2{$Obyq}L%K`F zWgoaWXa7TnH1A4ax4e(oG)N32i^%Pn!%Za+3TsIZ8UD?Vrtp3OMJ9u`h4qIm9)({o zo!9gm2?~r_>S_e7ovDTmPSFnT=#8*q&sc~hJ#}aafSXtJCrtla^BR7HW3Y-Os`#&Z zy1wA)Bg5m2a^u`31!*pj;HRYOZQj;|w(te}fDgpEOc$()QX7I}4 z4{{U+qB+=Zw29~F6nHPfiO%h%bqvs%UFm}yNwh$Jb?{VUn`<|p4=vS}JMUXj_bj}c zwG3adzOX!&_bqz)sZV~=&lzQYt>uz(H^tHVO&8-9Zq#zonc^pF!kgEUXYY<9EuEQ! zkug&Re0}dazs+(y8RqDxnvoZJDPDE=*9Mc>I+~Jb5)I=^Kw-WNqNGKgjAftMA)PV# Xk<&R|#Ol@?#JdtsP#rz59*6$`jflDL literal 1344 zcmezO_TO6u1_mY|W&~rQ;>_HFoK)S6l9B@5;?$zD)FPmie$PwZ>p;5Spoy{DfRBw! zn~jl$QHx2Ck&%^wrHQfp)N!H413LsXN{ZXQ``uU?Ol=zhzh%HD7v+ePcNw3fbI zXEfDy{)q;0o*#)n8?w^3Hox7e9uB)H8kR(3*Wyk4Pq;2qx+KO16B z=!T1l=bQK%uzWnpaPxA@mv0}pSRD8rJRwN3PUglAk1ti*xwV(uOxSRTx7s?`*qzVf z>rW}WgcsY7Oj{Xk#jx^_OIJjIY%)u~hS8)qy;Ef`opN_kX4qC68@1!MlsW%`BYnSm zmNmvc`|)nc{jg<@$5iCE2VII+w(;Jte(_JnNz0>_H{(_;`F5(ZNWM|Tm_g2dUPegV z=I@gYT+c9ZGJi3-x%!@8^Pc_vM{Kow!!Pd@xa};me0Rh|zQ@-^;)JfLtME)+b}BsB zy#Dx|6Kh&y)5Kq}am@g(T9PX{W`8%^_-pSf=Vjn1V~x-= zHLzr0V2(3rVvYi0@deCGj7&@{zFVu647l0Ywc0$+S+Fp(G8i=W8wvoUk2#cuO_)72 zFFP;4JP#(qfg!?<5K%Tz1nJ@umU1jeOwLGE2+mI{DNig)RdCBM%}Yrv$;{6)lrxY4 zDdH9ug(~s@CL-tj+=BeP)Vz{nLm>kJkUX<6XHI@{VopYWafyMPIIp3hfr*i+p|OdX zp+OXwYi?u$em&~94 zf~8tO>5%{KmDm4mKPLUdI{f*u70X2VS$;QvyL?pcFq3JBaFp0Yqi?03*J&qS*Lwd+ ziCJ>)MGwZ~Ori|a69W20mATJsnzXZN(d!oO4-qn7K~DSra6#*}*|zsi?^zvVwj+FJ z<&^cie_6e1`Wf!SZOh)29vB(kx9duz|Fc4NfyRa{o??Z{FMKq_gtwpPH0n9A?4gZV zRd+~Duf~JL>*TaIFDspxx454Bm!fIX$KOd+j4IY=mVDf|B5*?Iist(dqn^%Zo79~a z*H9g*n!@N~{qMY|7IR|@15;yz>0+P0+f&ZU^(~yTZqkJ5(;fzVun(N4zm%cAvC`jr z?WVPjchZk>L~m7p`)D%VcVTMrD$hR?;qZEp8AdH*+A%{-4S)wO?4 b)xWi;ALp8_yfsJQWbmc~e~(4!EN}q;sl*hE From eb27f9ee2946e6aa0741fa089e1188b38fe3c530 Mon Sep 17 00:00:00 2001 From: Aleksei Arsenev Date: Fri, 11 May 2018 13:14:47 +0300 Subject: [PATCH 182/204] HTTPCLIENT-1923: fixed incorrect connection close on shutdown + fixed corresponding test --- .../BasicHttpClientConnectionManager.java | 26 +++++-------------- .../TestBasicHttpClientConnectionManager.java | 4 +-- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java index 5f694436d2..10aef9f34d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java @@ -157,7 +157,9 @@ protected void finalize() throws Throwable { @Override public void close() { - shutdown(); + if (this.isShutdown.compareAndSet(false, true)) { + closeConnection(); + } } HttpRoute getRoute() { @@ -206,7 +208,7 @@ public HttpClientConnection get(final long timeout, final TimeUnit tunit) { }; } - private void closeConnection() { + private synchronized void closeConnection() { if (this.conn != null) { this.log.debug("Closing connection"); try { @@ -220,20 +222,6 @@ private void closeConnection() { } } - private void shutdownConnection() { - if (this.conn != null) { - this.log.debug("Shutting down connection"); - try { - this.conn.shutdown(); - } catch (final IOException iox) { - if (this.log.isDebugEnabled()) { - this.log.debug("I/O exception shutting down connection", iox); - } - } - this.conn = null; - } - } - private void checkExpiry() { if (this.conn != null && System.currentTimeMillis() >= this.expiry) { if (this.log.isDebugEnabled()) { @@ -373,10 +361,8 @@ public synchronized void closeIdleConnections(final long idletime, final TimeUni } @Override - public synchronized void shutdown() { - if (this.isShutdown.compareAndSet(false, true)) { - shutdownConnection(); - } + public void shutdown() { + close(); } } diff --git a/httpclient/src/test/java/org/apache/http/impl/conn/TestBasicHttpClientConnectionManager.java b/httpclient/src/test/java/org/apache/http/impl/conn/TestBasicHttpClientConnectionManager.java index b64bb7e529..279793a213 100644 --- a/httpclient/src/test/java/org/apache/http/impl/conn/TestBasicHttpClientConnectionManager.java +++ b/httpclient/src/test/java/org/apache/http/impl/conn/TestBasicHttpClientConnectionManager.java @@ -278,7 +278,7 @@ public void testShutdown() throws Exception { mgr.shutdown(); - Mockito.verify(conn, Mockito.times(1)).shutdown(); + Mockito.verify(conn, Mockito.times(1)).close(); try { final ConnectionRequest connRequest2 = mgr.requestConnection(route, null); @@ -292,7 +292,7 @@ public void testShutdown() throws Exception { mgr.closeIdleConnections(0L, TimeUnit.MILLISECONDS); mgr.shutdown(); - Mockito.verify(conn, Mockito.times(1)).shutdown(); + Mockito.verify(conn, Mockito.times(1)).close(); } @Test From 7c193f6141f0f321649127d9bcd0afc4a9189a3b Mon Sep 17 00:00:00 2001 From: Varun Nandi Date: Thu, 7 Jun 2018 10:13:19 -0700 Subject: [PATCH 183/204] Add Automatic-Module-Name in manifest so Java9 modular applications can depend on this library --- fluent-hc/pom.xml | 22 ++++++++++++++++++++++ httpclient-cache/pom.xml | 10 ++++++++++ httpclient-win/pom.xml | 25 +++++++++++++++++++++++++ httpclient/pom.xml | 10 ++++++++++ httpmime/pom.xml | 19 +++++++++++++++++++ 5 files changed, 86 insertions(+) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index e02fbbe38f..08f351b886 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -81,6 +81,28 @@ + + + org.apache.maven.plugins + maven-jar-plugin + + + default-jar + package + + jar + + + + + org.apache.httpcomponents.fluent-hc + + + + + + + diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index e23149293a..7279d7b8e5 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -133,9 +133,19 @@ maven-jar-plugin + default-jar + package + jar test-jar + + + + org.apache.httpcomponents.httpclient-cache + + + diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index cdc948af03..d045a2b785 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -69,6 +69,31 @@ + + + + org.apache.maven.plugins + maven-jar-plugin + + + default-jar + package + + jar + + + + + org.apache.httpcomponents.httpclient-win + + + + + + + + + diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 56a589dfba..c8e366c6a1 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -119,9 +119,19 @@ maven-jar-plugin + default-jar + package + jar test-jar + + + + org.apache.httpcomponents.httpclient + + + diff --git a/httpmime/pom.xml b/httpmime/pom.xml index ba07fa233e..308e76f0f3 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -89,6 +89,25 @@ + + maven-jar-plugin + + + default-jar + package + + jar + + + + + org.apache.httpcomponents.httpmime + + + + + + From ca98ad69adad79de57d8b944ba524f7267a795cb Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 16 Jun 2018 10:33:24 +0200 Subject: [PATCH 184/204] HTTPCLIENT-1924: HttpClient to shut down the connection manager if a fatal error occurs in the course of a request execution --- .../java/org/apache/http/impl/execchain/MainClientExec.java | 3 +++ .../java/org/apache/http/impl/execchain/MinimalClientExec.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java index 579ffedde2..0124f91150 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java @@ -355,6 +355,9 @@ public CloseableHttpResponse execute( } catch (final RuntimeException ex) { connHolder.abortConnection(); throw ex; + } catch (final Error error) { + connManager.shutdown(); + throw error; } } diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java index bc82904385..113c6956cc 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java @@ -247,6 +247,9 @@ public CloseableHttpResponse execute( } catch (final RuntimeException ex) { releaseTrigger.abortConnection(); throw ex; + } catch (final Error error) { + connManager.shutdown(); + throw error; } } From 1fb095e6c92d4ebdf55321675b49243b95f1481e Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 3 Jul 2018 11:56:46 +0200 Subject: [PATCH 185/204] Upgraded HttpCore dependency to version 4.4.10 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 03183c2b11..5af5bcfa3f 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 1.6 1.6 - 4.4.9 + 4.4.10 1.2 1.10 2.6.11 From 060cf48d4bbca8e040cda180e0a0e879bf41383d Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 4 Jul 2018 14:40:14 +0200 Subject: [PATCH 186/204] HTTPCLIENT-1882: reset authentication state on I/O or runtime error for connection based authentication schemes (such as NTLM) --- .../java/org/apache/http/auth/AuthState.java | 9 +++++++++ .../http/impl/execchain/MainClientExec.java | 18 ++++++++++++++---- .../http/impl/execchain/RedirectExec.java | 10 +++------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthState.java b/httpclient/src/main/java/org/apache/http/auth/AuthState.java index 64febf36f7..89ef53b9a6 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthState.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthState.java @@ -133,6 +133,15 @@ public boolean hasAuthOptions() { return this.authOptions != null && !this.authOptions.isEmpty(); } + /** + * Returns {@code true} if the actual authentication scheme is connection based. + * + * @since 4.5.6 + */ + public boolean isConnectionBased() { + return this.authScheme != null && this.authScheme.isConnectionBased(); + } + /** * Updates the auth state with a queue of {@link AuthOption}s. * diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java index 0124f91150..99dd347b21 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java @@ -299,14 +299,12 @@ public CloseableHttpResponse execute( } else { managedConn.close(); if (proxyAuthState.getState() == AuthProtocolState.SUCCESS - && proxyAuthState.getAuthScheme() != null - && proxyAuthState.getAuthScheme().isConnectionBased()) { + && proxyAuthState.isConnectionBased()) { this.log.debug("Resetting proxy auth state"); proxyAuthState.reset(); } if (targetAuthState.getState() == AuthProtocolState.SUCCESS - && targetAuthState.getAuthScheme() != null - && targetAuthState.getAuthScheme().isConnectionBased()) { + && targetAuthState.isConnectionBased()) { this.log.debug("Resetting target auth state"); targetAuthState.reset(); } @@ -351,9 +349,21 @@ public CloseableHttpResponse execute( throw ex; } catch (final IOException ex) { connHolder.abortConnection(); + if (proxyAuthState.isConnectionBased()) { + proxyAuthState.reset(); + } + if (targetAuthState.isConnectionBased()) { + targetAuthState.reset(); + } throw ex; } catch (final RuntimeException ex) { connHolder.abortConnection(); + if (proxyAuthState.isConnectionBased()) { + proxyAuthState.reset(); + } + if (targetAuthState.isConnectionBased()) { + targetAuthState.reset(); + } throw ex; } catch (final Error error) { connManager.shutdown(); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java index 37549e1c0b..2deb75444b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RedirectExec.java @@ -40,7 +40,6 @@ import org.apache.http.ProtocolException; import org.apache.http.annotation.Contract; import org.apache.http.annotation.ThreadingBehavior; -import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthState; import org.apache.http.client.RedirectException; import org.apache.http.client.RedirectStrategy; @@ -146,12 +145,9 @@ public CloseableHttpResponse execute( targetAuthState.reset(); } final AuthState proxyAuthState = context.getProxyAuthState(); - if (proxyAuthState != null) { - final AuthScheme authScheme = proxyAuthState.getAuthScheme(); - if (authScheme != null && authScheme.isConnectionBased()) { - this.log.debug("Resetting proxy auth state"); - proxyAuthState.reset(); - } + if (proxyAuthState != null && proxyAuthState.isConnectionBased()) { + this.log.debug("Resetting proxy auth state"); + proxyAuthState.reset(); } } From 03d316b47b6da478f3a100886af68440ec4f8134 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 5 Jul 2018 13:22:47 +0200 Subject: [PATCH 187/204] Updated release notes for HttpClient 4.5.6 release --- RELEASE_NOTES.txt | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index d2f7d363bc..0d96723bb7 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,14 +1,40 @@ Release 4.5.6 ------------------- -HttpClient 4.5.6 (GA) is a maintenance release. +This is a maintenance release that adds Automatic-Module-Name to the manifest for compatibility +with Java 9 Platform Module System and fixes a number of issues discovered since 4.5.5 Please note that as of 4.4 HttpClient requires Java 1.6 or newer. Changelog: ------------------- -* [HTTPCLIENT-1911]: Failing tests on Fedora 28 due to weak encryption algorithms in test keystore. +* [HTTPCLIENT-1882=: reset authentication state on I/O or runtime error for connection based + authentication schemes (such as NTLM) + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1924]: HttpClient to shut down the connection manager if a fatal error occurs + in the course of a request execution. + Contributed by Oleg Kalnichevski + +* Add Automatic-Module-Name in manifest so Java9 modular applications can depend on this library + Contributed by Varun Nandi + +* [HTTPCLIENT-1923]: fixed incorrect connection close on shutdown + fixed corresponding test + Contributed by Aleksei Arsenev + +* [HTTPCLIENT-1906]: certificates containing alternative subject names other than DNS and IP + (such as RFC822) get rejected as invalid + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1904]: check cookie domain for null + Contributed by Hans-Peter Keck + +* [HTTPCLIENT-1900]: proxy protocol processor does not post-process CONNECT response messages + Contributed by Oleg Kalnichevski + +* [HTTPCLIENT-1911]: Failing tests on Fedora 28 due to weak encryption algorithms in test + keystore. Contributed by Gary Gregory and Michael Simacek From 1480958ce75c42977101432172e1245c3f555f5b Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 5 Jul 2018 13:39:40 +0200 Subject: [PATCH 188/204] HttpClient 4.5.6 release --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 08f351b886..15ee18b1d5 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6-SNAPSHOT + 4.5.6 fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 7279d7b8e5..0bdb8d0ea9 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6-SNAPSHOT + 4.5.6 httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 3e7d012a0d..4ac9333fd7 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6-SNAPSHOT + 4.5.6 httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index d045a2b785..08293fbf83 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6-SNAPSHOT + 4.5.6 httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index c8e366c6a1..88117e6bc9 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6-SNAPSHOT + 4.5.6 httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index 308e76f0f3..28f459f8a2 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6-SNAPSHOT + 4.5.6 httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 5af5bcfa3f..32e208dba7 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.6-SNAPSHOT + 4.5.6 Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 @@ -61,7 +61,7 @@ scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 4.5.6-SNAPSHOT + 4.5.6 From ce33e88b1d6947a5fa2a702638eb7f3c138941b6 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 9 Jul 2018 10:03:20 +0200 Subject: [PATCH 189/204] Upgraded HttpClient version to 4.5.7-SNAPSHOT --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-osgi/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- httpclient/pom.xml | 2 +- httpmime/pom.xml | 2 +- pom.xml | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 15ee18b1d5..3fb0a9bd74 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6 + 4.5.7-SNAPSHOT fluent-hc Apache HttpClient Fluent API diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 0bdb8d0ea9..2eb20c297a 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6 + 4.5.7-SNAPSHOT httpclient-cache Apache HttpClient Cache diff --git a/httpclient-osgi/pom.xml b/httpclient-osgi/pom.xml index 4ac9333fd7..d216733235 100644 --- a/httpclient-osgi/pom.xml +++ b/httpclient-osgi/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6 + 4.5.7-SNAPSHOT httpclient-osgi Apache HttpClient OSGi bundle diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index 08293fbf83..18a4481503 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6 + 4.5.7-SNAPSHOT httpclient-win Apache HttpClient Windows features diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 88117e6bc9..fc2c29e937 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6 + 4.5.7-SNAPSHOT httpclient Apache HttpClient diff --git a/httpmime/pom.xml b/httpmime/pom.xml index 28f459f8a2..eabfda5d62 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents httpcomponents-client - 4.5.6 + 4.5.7-SNAPSHOT httpmime Apache HttpClient Mime diff --git a/pom.xml b/pom.xml index 32e208dba7..846c6dc243 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 4.0.0 httpcomponents-client Apache HttpComponents Client - 4.5.6 + 4.5.7-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services http://hc.apache.org/httpcomponents-client-ga/ 1999 @@ -61,7 +61,7 @@ scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git scm:git:https://git-wip-us.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 4.5.6 + 4.5.7-SNAPSHOT From 5fea3e0439df77c91c34c5b6482ad79770b63d0c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 7 Jul 2018 11:12:34 +0200 Subject: [PATCH 190/204] HTTPCLIENT-1927: URLEncodedUtils#parse breaks at double quotes when parsing unquoted values --- .../java/org/apache/http/client/utils/URLEncodedUtils.java | 2 +- .../org/apache/http/client/utils/TestURLEncodedUtils.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index 5139d8670f..cc9066adcb 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -305,7 +305,7 @@ public static List parse( cursor.updatePos(cursor.getPos() + 1); if (delim == '=') { delimSet.clear('='); - value = tokenParser.parseValue(buf, cursor, delimSet); + value = tokenParser.parseToken(buf, cursor, delimSet); if (!cursor.atEnd()) { cursor.updatePos(cursor.getPos() + 1); } diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java index 0041f0f00f..89dfc6dbb5 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURLEncodedUtils.java @@ -95,6 +95,11 @@ public void testParseURLCodedContent() throws Exception { result = parse("price=10%20%E2%82%AC"); Assert.assertEquals(1, result.size()); assertNameValuePair(result.get(0), "price", "10 \u20AC"); + + result = parse("a=b\"c&d=e"); + Assert.assertEquals(2, result.size()); + assertNameValuePair(result.get(0), "a", "b\"c"); + assertNameValuePair(result.get(1), "d", "e"); } @Test From c72ccfaba8e866a202184fc467a41df467078efe Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 9 Jul 2018 13:56:13 +0200 Subject: [PATCH 191/204] HTTPCLIENT-1929: Corrected Automatic-Module-Name entries for HttpClient Fluent, HttpClient Windows and HttpClient Cache --- fluent-hc/pom.xml | 2 +- httpclient-cache/pom.xml | 2 +- httpclient-win/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fluent-hc/pom.xml b/fluent-hc/pom.xml index 3fb0a9bd74..c4a2675a16 100644 --- a/fluent-hc/pom.xml +++ b/fluent-hc/pom.xml @@ -95,7 +95,7 @@ - org.apache.httpcomponents.fluent-hc + org.apache.httpcomponents.httpclient.fluent diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 2eb20c297a..89dc1c3eaa 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -142,7 +142,7 @@ - org.apache.httpcomponents.httpclient-cache + org.apache.httpcomponents.httpclient.cache diff --git a/httpclient-win/pom.xml b/httpclient-win/pom.xml index 18a4481503..374d84a64c 100644 --- a/httpclient-win/pom.xml +++ b/httpclient-win/pom.xml @@ -84,7 +84,7 @@ - org.apache.httpcomponents.httpclient-win + org.apache.httpcomponents.httpclient.win From 8c3333b4d53ba423c5f98df1ddf8bf85d3923bfc Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 12 Jul 2018 09:04:46 -0600 Subject: [PATCH 192/204] Use "String.isEmpty()" instead of "String.length() == 0" --- .../main/java/org/apache/http/client/utils/URLEncodedUtils.java | 2 +- .../java/org/apache/http/impl/cookie/RFC6265CookieSpec.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index cc9066adcb..d85cf8d654 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -141,7 +141,7 @@ public static List parse( } finally { instream.close(); } - if (buf.length() == 0) { + if (buf.isEmpty()) { return createEmptyList(); } return parse(buf, charset, QP_SEP_A); diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java index 7368dcfe2f..d17901172a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC6265CookieSpec.java @@ -130,7 +130,7 @@ public final List parse(final Header header, final CookieOrigin origin) cursor = new ParserCursor(0, buffer.length()); } final String name = tokenParser.parseToken(buffer, cursor, TOKEN_DELIMS); - if (name.length() == 0) { + if (name.isEmpty()) { return Collections.emptyList(); } if (cursor.atEnd()) { From 3b4258817aa188e45f3b064c0ea714fc9620ce91 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 5 Aug 2018 11:33:36 -0600 Subject: [PATCH 193/204] Remove exceptions not thrown from method signatures. Don't nest unnecessarily. --- .../org/apache/http/impl/execchain/MainClientExec.java | 6 ++---- .../apache/http/impl/execchain/MinimalClientExec.java | 9 +++------ .../apache/http/impl/execchain/ResponseEntityProxy.java | 4 ++-- .../java/org/apache/http/impl/execchain/RetryExec.java | 3 +-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java index 99dd347b21..271d796c41 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java @@ -178,9 +178,8 @@ public CloseableHttpResponse execute( if (execAware.isAborted()) { connRequest.cancel(); throw new RequestAbortedException("Request aborted"); - } else { - execAware.setCancellable(connRequest); } + execAware.setCancellable(connRequest); } final RequestConfig config = context.getRequestConfig(); @@ -336,9 +335,8 @@ public CloseableHttpResponse execute( // connection not needed and (assumed to be) in re-usable state connHolder.releaseConnection(); return new HttpResponseProxy(response, null); - } else { - return new HttpResponseProxy(response, connHolder); } + return new HttpResponseProxy(response, connHolder); } catch (final ConnectionShutdownException ex) { final InterruptedIOException ioex = new InterruptedIOException( "Connection has been shut down"); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java index 113c6956cc..e2fbcc01c5 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/MinimalClientExec.java @@ -146,9 +146,8 @@ public CloseableHttpResponse execute( if (execAware.isAborted()) { connRequest.cancel(); throw new RequestAbortedException("Request aborted"); - } else { - execAware.setCancellable(connRequest); } + execAware.setCancellable(connRequest); } final RequestConfig config = context.getRequestConfig(); @@ -174,9 +173,8 @@ public CloseableHttpResponse execute( if (execAware.isAborted()) { releaseTrigger.close(); throw new RequestAbortedException("Request aborted"); - } else { - execAware.setCancellable(releaseTrigger); } + execAware.setCancellable(releaseTrigger); } if (!managedConn.isOpen()) { @@ -230,9 +228,8 @@ public CloseableHttpResponse execute( // connection not needed and (assumed to be) in re-usable state releaseTrigger.releaseConnection(); return new HttpResponseProxy(response, null); - } else { - return new HttpResponseProxy(response, releaseTrigger); } + return new HttpResponseProxy(response, releaseTrigger); } catch (final ConnectionShutdownException ex) { final InterruptedIOException ioex = new InterruptedIOException( "Connection has been shut down"); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java index 7013e09ebd..6f53c23140 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java @@ -65,13 +65,13 @@ private void cleanup() throws IOException { } } - private void abortConnection() throws IOException { + private void abortConnection() { if (this.connHolder != null) { this.connHolder.abortConnection(); } } - public void releaseConnection() throws IOException { + public void releaseConnection() { if (this.connHolder != null) { this.connHolder.releaseConnection(); } diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java index 201733e9bb..42039fb0ad 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RetryExec.java @@ -118,9 +118,8 @@ public CloseableHttpResponse execute( route.getTargetHost().toHostString() + " failed to respond"); updatedex.setStackTrace(ex.getStackTrace()); throw updatedex; - } else { - throw ex; } + throw ex; } } } From 517396df0ce598d29b7f77d3bf977e26e651b217 Mon Sep 17 00:00:00 2001 From: Mark Mielke Date: Wed, 8 Aug 2018 06:43:55 -0400 Subject: [PATCH 194/204] Fix HttpClient 4.5.4 regression in BasicCookieStore serialization. HttpClient 4.5.4 modified BasicCookieStore to introduce a new ReadWriteLock field to improve performance. Unfortunately this also changed the serialized data structure, and any objects serialized using HttpClient 4.5.3 and before would be unusable after restore in HttpClient 4.5.4 due to the new "lock" field being null. The fix is to change "lock" to be transient, and ensure it is correctly instantiated upon object restore. This restores compatibility with HttpClient 4.5.3, as well as maintaining compatible with the intermediate versions containing the regression. This also avoids unnecessary serialization of the new "lock" field, which does not need to be persisted. --- .../org/apache/http/impl/client/BasicCookieStore.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java index c536c6e18f..6f81a22e3f 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicCookieStore.java @@ -26,6 +26,8 @@ */ package org.apache.http.impl.client; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; @@ -53,7 +55,7 @@ public class BasicCookieStore implements CookieStore, Serializable { private static final long serialVersionUID = -7581093305228232025L; private final TreeSet cookies; - private final ReadWriteLock lock; + private transient ReadWriteLock lock; public BasicCookieStore() { super(); @@ -61,6 +63,13 @@ public BasicCookieStore() { this.lock = new ReentrantReadWriteLock(); } + private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + + /* Reinstantiate transient fields. */ + this.lock = new ReentrantReadWriteLock(); + } + /** * Adds an {@link Cookie HTTP cookie}, replacing any existing equivalent cookies. * If the given cookie has already expired it will not be added, but existing From 681d11e265090bf6efa7dd6e19772a746c174b0e Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 11 Aug 2018 20:20:25 +0200 Subject: [PATCH 195/204] HTTPCLIENT-1940: deprecated SSLSocketFactory made to rethrow SocketTimeoutException as ConnectTimeoutException for consistency with non-deprecated code --- .../org/apache/http/conn/ssl/SSLSocketFactory.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java index 8c7fee5a55..aecbfe14f3 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/ssl/SSLSocketFactory.java @@ -31,6 +31,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; @@ -540,12 +541,8 @@ public Socket connectSocket( } try { sock.connect(remoteAddress, connectTimeout); - } catch (final IOException ex) { - try { - sock.close(); - } catch (final IOException ignore) { - } - throw ex; + } catch (final SocketTimeoutException ex) { + throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out"); } // Setup SSL layering if necessary if (sock instanceof SSLSocket) { From b9a286ed933e90bd4e89ca3da7545f831b6bc1c3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 13 Aug 2018 13:02:47 -0600 Subject: [PATCH 196/204] [HTTPCLIENT-1939] Update Apache Commons Codec from 1.10 to 1.11. --- RELEASE_NOTES.txt | 34 ++++++++++++++++++++++++---------- pom.xml | 2 +- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 0d96723bb7..c989931533 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,10 +1,24 @@ +Release 4.5.7 +------------------- + +This is a maintenance release. + +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. + +Changelog: +------------------- + +* HTTPCLIENT-1939: Update Apache Commons Codec from 1.10 to 1.11 + Contributed by Gary Gregory + + Release 4.5.6 ------------------- This is a maintenance release that adds Automatic-Module-Name to the manifest for compatibility with Java 9 Platform Module System and fixes a number of issues discovered since 4.5.5 -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: ------------------- @@ -44,7 +58,7 @@ Release 4.5.5 HttpClient 4.5.5 (GA) is a maintenance release that fixes a regression introduced by the previous release causing a NPE in SystemDefaultCredentialsProvider. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: ------------------- @@ -68,7 +82,7 @@ Release 4.5.4 HttpClient 4.5.4 (GA) is a maintenance release that fixes a number of defects found since 4.5.3. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: ------------------- @@ -138,7 +152,7 @@ Release 4.5.3 HttpClient 4.5.3 (GA) is a maintenance release that fixes a number of defects found since 4.5.2. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: ------------------- @@ -215,7 +229,7 @@ Release 4.5.2 HttpClient 4.5.2 (GA) is a maintenance release that fixes a number of minor defects found since 4.5.1. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: ------------------- @@ -265,7 +279,7 @@ Release 4.5.1 HttpClient 4.5.1 (GA) is a maintenance release that fixes a number of minor defects found since 4.5. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: ------------------- @@ -332,7 +346,7 @@ introduced in version 4.4. Users of HttpClient 4.4 are encouraged to upgrade. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: ------------------- @@ -390,7 +404,7 @@ Use at your discretion. This release also includes all fixes from the stable 4.3.x release branch. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: @@ -456,7 +470,7 @@ requests This release also includes all fixes from the stable 4.3.x release branch. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Changelog: @@ -500,7 +514,7 @@ requests This release also includes all fixes from the stable 4.3.x release branch. -Please note that as of 4.4 HttpClient requires Java 1.6 or newer. +Please note that as of 4.4, HttpClient requires Java 1.6 or newer. Please note that new features included in this release are still considered experimental and their API may change in the future 4.4 alpha and beta releases. diff --git a/pom.xml b/pom.xml index 846c6dc243..1930e5702f 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ 1.6 4.4.10 1.2 - 1.10 + 1.11 2.6.11 2.12.3 1.7.25 From e6c226d5f6f34db4bd86aa81168289ac81a0896a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 13 Aug 2018 16:47:47 -0600 Subject: [PATCH 197/204] - Always use blocks - Add missing serial version ID (default 1L) - Camel-case names. - Don't nest in else clause unnecessarily. - Remove declared exceptions that are not thrown (but don't break BC.) - Remove redundant superinterface - Access static methods directly - Better local var names. --- .../fluent/InternalByteArrayEntity.java | 8 +-- .../client/fluent/InternalFileEntity.java | 14 ++--- .../fluent/InternalInputStreamEntity.java | 26 +++++----- .../apache/http/client/fluent/Request.java | 8 +-- .../http/client/cache/ResourceFactory.java | 4 +- .../http/impl/client/cache/CacheEntity.java | 10 ++-- .../impl/client/cache/CombinedEntity.java | 16 +++--- .../client/cache/FileResourceFactory.java | 10 ++-- .../client/cache/HeapResourceFactory.java | 16 +++--- .../http/impl/client/cache/IOUtils.java | 6 +-- .../cache/SizeLimitedResponseReader.java | 10 ++-- .../impl/client/cache/TestCombinedEntity.java | 4 +- .../client/ClientConnectionRelease.java | 6 +-- .../apache/http/conn/BasicManagedEntity.java | 4 +- .../conn/BasicClientConnectionManager.java | 14 ++--- .../impl/conn/DefaultClientConnection.java | 16 +++--- .../apache/http/impl/conn/HttpConnPool.java | 8 +-- .../apache/http/impl/conn/HttpPoolEntry.java | 4 +- .../impl/conn/LoggingSessionInputBuffer.java | 34 ++++++------ .../conn/PoolingClientConnectionManager.java | 28 +++++----- .../impl/conn/SingleClientConnManager.java | 8 +-- .../impl/conn/tsccm/AbstractConnPool.java | 14 ++--- .../http/impl/conn/tsccm/ConnPoolByRoute.java | 20 +++---- .../impl/conn/tsccm/PoolEntryRequest.java | 4 +- .../tsccm/ThreadSafeClientConnManager.java | 10 ++-- .../apache/http/auth/AuthSchemeRegistry.java | 3 +- .../client/entity/DecompressingEntity.java | 15 +++--- .../client/entity/GzipCompressingEntity.java | 6 +-- .../client/entity/InputStreamFactory.java | 2 +- .../client/methods/HttpRequestWrapper.java | 9 ++-- .../client/protocol/HttpClientContext.java | 8 ++- .../apache/http/client/utils/CloneUtils.java | 6 +-- .../apache/http/client/utils/URIBuilder.java | 8 ++- .../apache/http/client/utils/URIUtils.java | 18 ++----- .../http/client/utils/URLEncodedUtils.java | 8 +-- .../http/conn/ClientConnectionManager.java | 4 +- .../http/conn/ClientConnectionRequest.java | 4 +- .../apache/http/conn/ConnectionRequest.java | 4 +- .../http/conn/EofSensorInputStream.java | 16 +++--- .../conn/HttpClientConnectionManager.java | 4 +- .../http/conn/ManagedClientConnection.java | 3 +- .../apache/http/conn/routing/HttpRoute.java | 24 +++------ .../org/apache/http/conn/scheme/Scheme.java | 14 ++--- .../scheme/SchemeSocketFactoryAdaptor.java | 8 ++- .../conn/scheme/SocketFactoryAdaptor.java | 8 ++- .../http/conn/ssl/AbstractVerifier.java | 3 +- .../conn/ssl/SSLConnectionSocketFactory.java | 3 +- .../http/conn/util/PublicSuffixMatcher.java | 6 +-- .../http/cookie/CookieSpecRegistry.java | 3 +- .../apache/http/impl/auth/AuthSchemeBase.java | 6 +-- .../apache/http/impl/auth/DigestScheme.java | 6 +-- .../apache/http/impl/auth/GGSSchemeBase.java | 8 ++- .../http/impl/auth/HttpAuthenticator.java | 52 ++++++++----------- .../apache/http/impl/auth/NTLMEngineImpl.java | 30 +++++------ .../http/impl/client/BasicAuthCache.java | 6 +-- .../DefaultHttpRequestRetryHandler.java | 9 ++-- .../impl/client/DefaultRedirectStrategy.java | 8 ++- .../client/EntityEnclosingRequestWrapper.java | 4 +- .../impl/client/HttpRequestFutureTask.java | 9 ++-- .../impl/client/HttpRequestTaskCallable.java | 3 +- .../impl/client/IdleConnectionEvictor.java | 4 +- .../http/impl/client/InternalHttpClient.java | 4 +- .../http/impl/client/MinimalHttpClient.java | 4 +- .../SystemDefaultCredentialsProvider.java | 18 +++---- .../BasicHttpClientConnectionManager.java | 14 ++--- .../java/org/apache/http/impl/conn/CPool.java | 8 +-- .../org/apache/http/impl/conn/CPoolEntry.java | 4 +- .../org/apache/http/impl/conn/CPoolProxy.java | 24 ++------- .../DefaultHttpClientConnectionOperator.java | 8 ++- .../DefaultManagedHttpClientConnection.java | 18 +++---- .../http/impl/conn/DefaultRoutePlanner.java | 8 ++- .../LoggingManagedHttpClientConnection.java | 30 +++++------ .../ManagedHttpClientConnectionFactory.java | 28 +++++----- .../PoolingHttpClientConnectionManager.java | 30 +++++------ .../java/org/apache/http/impl/conn/Wire.java | 16 +++--- .../http/impl/cookie/DefaultCookieSpec.java | 51 ++++++++---------- .../http/impl/cookie/LaxExpiresHandler.java | 5 +- .../apache/http/impl/cookie/RFC2109Spec.java | 6 +-- .../apache/http/impl/cookie/RFC2965Spec.java | 20 +++---- .../http/impl/execchain/ConnectionHolder.java | 8 +-- .../impl/execchain/RequestEntityProxy.java | 4 +- .../impl/execchain/ResponseEntityProxy.java | 6 +-- .../org/apache/http/auth/TestCredentials.java | 24 ++++----- .../entity/TestDecompressingEntity.java | 4 +- .../apache/http/client/entity/TestGZip.java | 3 +- .../client/methods/TestHttpRequestBase.java | 4 +- .../protocol/TestRequestAddCookies.java | 3 +- .../client/utils/TestHttpClientUtils.java | 24 ++++----- .../http/conn/TestEofSensorInputStream.java | 46 ++++++++-------- .../http/impl/client/MockConnPoolControl.java | 6 +-- .../client/TestAbstractResponseHandler.java | 6 +-- .../impl/client/TestBasicCookieStore.java | 28 +++++----- .../impl/client/TestBasicResponseHandler.java | 6 +-- .../client/TestIdleConnectionEvictor.java | 3 +- .../client/integration/TestAbortHandling.java | 15 +++--- .../TestConnectionAutoRelease.java | 6 +-- .../TestMalformedServerResponse.java | 4 +- .../impl/conn/SessionInputBufferMock.java | 26 +++++----- .../conn/TestDefaultHttpResponseParser.java | 16 +++--- .../impl/cookie/TestBasicClientCookie.java | 12 ++--- .../impl/cookie/TestBasicClientCookie2.java | 12 ++--- .../impl/cookie/TestRFC6265CookieSpec.java | 13 ++--- .../impl/execchain/TestMainClientExec.java | 42 +++++++-------- .../http/impl/execchain/TestRedirectExec.java | 18 +++---- .../execchain/TestResponseEntityWrapper.java | 30 +++++------ .../http/entity/mime/MultipartEntity.java | 4 +- .../http/entity/mime/MultipartFormEntity.java | 12 ++--- 107 files changed, 599 insertions(+), 716 deletions(-) diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalByteArrayEntity.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalByteArrayEntity.java index b2702d1154..986095fb3c 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalByteArrayEntity.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalByteArrayEntity.java @@ -91,10 +91,10 @@ public InputStream getContent() { } @Override - public void writeTo(final OutputStream outstream) throws IOException { - Args.notNull(outstream, "Output stream"); - outstream.write(this.b, this.off, this.len); - outstream.flush(); + public void writeTo(final OutputStream outStream) throws IOException { + Args.notNull(outStream, "Output stream"); + outStream.write(this.b, this.off, this.len); + outStream.flush(); } @Override diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalFileEntity.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalFileEntity.java index 39c2b44ba0..6681e5a863 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalFileEntity.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalFileEntity.java @@ -65,18 +65,18 @@ public InputStream getContent() throws IOException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { - Args.notNull(outstream, "Output stream"); - final InputStream instream = new FileInputStream(this.file); + public void writeTo(final OutputStream outStream) throws IOException { + Args.notNull(outStream, "Output stream"); + final InputStream inStream = new FileInputStream(this.file); try { final byte[] tmp = new byte[4096]; int l; - while ((l = instream.read(tmp)) != -1) { - outstream.write(tmp, 0, l); + while ((l = inStream.read(tmp)) != -1) { + outStream.write(tmp, 0, l); } - outstream.flush(); + outStream.flush(); } finally { - instream.close(); + inStream.close(); } } diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalInputStreamEntity.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalInputStreamEntity.java index 3a4704191f..701277ad5e 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalInputStreamEntity.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalInputStreamEntity.java @@ -40,9 +40,9 @@ class InternalInputStreamEntity extends AbstractHttpEntity { private final InputStream content; private final long length; - public InternalInputStreamEntity(final InputStream instream, final long length, final ContentType contentType) { + public InternalInputStreamEntity(final InputStream inputStream, final long length, final ContentType contentType) { super(); - this.content = Args.notNull(instream, "Source input stream"); + this.content = Args.notNull(inputStream, "Source input stream"); this.length = length; if (contentType != null) { setContentType(contentType.toString()); @@ -65,31 +65,31 @@ public InputStream getContent() throws IOException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { - Args.notNull(outstream, "Output stream"); - final InputStream instream = this.content; + public void writeTo(final OutputStream outStream) throws IOException { + Args.notNull(outStream, "Output stream"); + final InputStream inStream = this.content; try { final byte[] buffer = new byte[4096]; - int l; + int readLen; if (this.length < 0) { // consume until EOF - while ((l = instream.read(buffer)) != -1) { - outstream.write(buffer, 0, l); + while ((readLen = inStream.read(buffer)) != -1) { + outStream.write(buffer, 0, readLen); } } else { // consume no more than length long remaining = this.length; while (remaining > 0) { - l = instream.read(buffer, 0, (int)Math.min(4096, remaining)); - if (l == -1) { + readLen = inStream.read(buffer, 0, (int)Math.min(4096, remaining)); + if (readLen == -1) { break; } - outstream.write(buffer, 0, l); - remaining -= l; + outStream.write(buffer, 0, readLen); + remaining -= readLen; } } } finally { - instream.close(); + inStream.close(); } } diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java index 4c43f59395..4d21166e8e 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java @@ -401,12 +401,12 @@ public Request bodyByteArray(final byte[] b, final int off, final int len, final return body(new InternalByteArrayEntity(b, off, len, contentType)); } - public Request bodyStream(final InputStream instream) { - return body(new InternalInputStreamEntity(instream, -1, null)); + public Request bodyStream(final InputStream inStream) { + return body(new InternalInputStreamEntity(inStream, -1, null)); } - public Request bodyStream(final InputStream instream, final ContentType contentType) { - return body(new InternalInputStreamEntity(instream, -1, contentType)); + public Request bodyStream(final InputStream inStream, final ContentType contentType) { + return body(new InternalInputStreamEntity(inStream, -1, contentType)); } @Override diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/ResourceFactory.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/ResourceFactory.java index 09664799c0..96a722597e 100644 --- a/httpclient-cache/src/main/java/org/apache/http/client/cache/ResourceFactory.java +++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/ResourceFactory.java @@ -41,7 +41,7 @@ public interface ResourceFactory { * Creates a {@link Resource} from a given response body. * @param requestId a unique identifier for this particular * response body - * @param instream the original {@link InputStream} + * @param inStream the original {@link InputStream} * containing the response body of the origin HTTP response. * @param limit maximum number of bytes to consume of the * response body; if this limit is reached before the @@ -52,7 +52,7 @@ public interface ResourceFactory { * the response body was successfully read. * @throws IOException */ - Resource generate(String requestId, InputStream instream, InputLimit limit) throws IOException; + Resource generate(String requestId, InputStream inStream, InputLimit limit) throws IOException; /** * Clones an existing {@link Resource}. diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java index 529d6983aa..9a9bb0424b 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java @@ -82,13 +82,13 @@ public InputStream getContent() throws IOException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { - Args.notNull(outstream, "Output stream"); - final InputStream instream = this.cacheEntry.getResource().getInputStream(); + public void writeTo(final OutputStream outStream) throws IOException { + Args.notNull(outStream, "Output stream"); + final InputStream inStream = this.cacheEntry.getResource().getInputStream(); try { - IOUtils.copy(instream, outstream); + IOUtils.copy(inStream, outStream); } finally { - instream.close(); + inStream.close(); } } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java index c665339a12..2a8f5fa12b 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CombinedEntity.java @@ -41,11 +41,11 @@ class CombinedEntity extends AbstractHttpEntity { private final Resource resource; private final InputStream combinedStream; - CombinedEntity(final Resource resource, final InputStream instream) throws IOException { + CombinedEntity(final Resource resource, final InputStream inStream) throws IOException { super(); this.resource = resource; this.combinedStream = new SequenceInputStream( - new ResourceStream(resource.getInputStream()), instream); + new ResourceStream(resource.getInputStream()), inStream); } @Override @@ -69,17 +69,17 @@ public InputStream getContent() throws IOException, IllegalStateException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { - Args.notNull(outstream, "Output stream"); - final InputStream instream = getContent(); + public void writeTo(final OutputStream outStream) throws IOException { + Args.notNull(outStream, "Output stream"); + final InputStream inStream = getContent(); try { int l; final byte[] tmp = new byte[2048]; - while ((l = instream.read(tmp)) != -1) { - outstream.write(tmp, 0, l); + while ((l = inStream.read(tmp)) != -1) { + outStream.write(tmp, 0, l); } } finally { - instream.close(); + inStream.close(); } } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java index b530eab1ae..b4bdbb627e 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/FileResourceFactory.java @@ -73,16 +73,16 @@ private File generateUniqueCacheFile(final String requestId) { @Override public Resource generate( final String requestId, - final InputStream instream, + final InputStream inStream, final InputLimit limit) throws IOException { final File file = generateUniqueCacheFile(requestId); - final FileOutputStream outstream = new FileOutputStream(file); + final FileOutputStream outStream = new FileOutputStream(file); try { final byte[] buf = new byte[2048]; long total = 0; int l; - while ((l = instream.read(buf)) != -1) { - outstream.write(buf, 0, l); + while ((l = inStream.read(buf)) != -1) { + outStream.write(buf, 0, l); total += l; if (limit != null && total > limit.getValue()) { limit.reached(); @@ -90,7 +90,7 @@ public Resource generate( } } } finally { - outstream.close(); + outStream.close(); } return new FileResource(file); } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java index 8cb9a2d82a..e00526e7ab 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeapResourceFactory.java @@ -47,21 +47,21 @@ public class HeapResourceFactory implements ResourceFactory { @Override public Resource generate( final String requestId, - final InputStream instream, + final InputStream inStream, final InputLimit limit) throws IOException { - final ByteArrayOutputStream outstream = new ByteArrayOutputStream(); + final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); final byte[] buf = new byte[2048]; long total = 0; int l; - while ((l = instream.read(buf)) != -1) { - outstream.write(buf, 0, l); + while ((l = inStream.read(buf)) != -1) { + outStream.write(buf, 0, l); total += l; if (limit != null && total > limit.getValue()) { limit.reached(); break; } } - return createResource(outstream.toByteArray()); + return createResource(outStream.toByteArray()); } @Override @@ -72,9 +72,9 @@ public Resource copy( if (resource instanceof HeapResource) { body = ((HeapResource) resource).getByteArray(); } else { - final ByteArrayOutputStream outstream = new ByteArrayOutputStream(); - IOUtils.copyAndClose(resource.getInputStream(), outstream); - body = outstream.toByteArray(); + final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + IOUtils.copyAndClose(resource.getInputStream(), outStream); + body = outStream.toByteArray(); } return createResource(body); } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java index 229bce681f..f4d6325da7 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/IOUtils.java @@ -43,9 +43,9 @@ static void consume(final HttpEntity entity) throws IOException { return; } if (entity.isStreaming()) { - final InputStream instream = entity.getContent(); - if (instream != null) { - instream.close(); + final InputStream inStream = entity.getContent(); + if (inStream != null) { + inStream.close(); } } } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java index f02e608bf2..d7749ef597 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/SizeLimitedResponseReader.java @@ -49,7 +49,7 @@ class SizeLimitedResponseReader { private final HttpRequest request; private final CloseableHttpResponse response; - private InputStream instream; + private InputStream inStream; private InputLimit limit; private Resource resource; private boolean consumed; @@ -99,12 +99,12 @@ private void doConsume() throws IOException { return; } final String uri = request.getRequestLine().getUri(); - instream = entity.getContent(); + inStream = entity.getContent(); try { - resource = resourceFactory.generate(uri, instream, limit); + resource = resourceFactory.generate(uri, inStream, limit); } finally { if (!limit.isReached()) { - instream.close(); + inStream.close(); } } } @@ -124,7 +124,7 @@ CloseableHttpResponse getReconstructedResponse() throws IOException { final HttpResponse reconstructed = new BasicHttpResponse(response.getStatusLine()); reconstructed.setHeaders(response.getAllHeaders()); - final CombinedEntity combinedEntity = new CombinedEntity(resource, instream); + final CombinedEntity combinedEntity = new CombinedEntity(resource, inStream); final HttpEntity entity = response.getEntity(); if (entity != null) { combinedEntity.setContentType(entity.getContentType()); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCombinedEntity.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCombinedEntity.java index 2e728bd0ba..b58ab63eb3 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCombinedEntity.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCombinedEntity.java @@ -45,8 +45,8 @@ public void testCombinedEntityBasics() throws Exception { when(resource.getInputStream()).thenReturn( new ByteArrayInputStream(new byte[] { 1, 2, 3, 4, 5 })); - final ByteArrayInputStream instream = new ByteArrayInputStream(new byte[] { 6, 7, 8, 9, 10 }); - final CombinedEntity entity = new CombinedEntity(resource, instream); + final ByteArrayInputStream inStream = new ByteArrayInputStream(new byte[] { 6, 7, 8, 9, 10 }); + final CombinedEntity entity = new CombinedEntity(resource, inStream); Assert.assertEquals(-1, entity.getContentLength()); Assert.assertFalse(entity.isRepeatable()); Assert.assertTrue(entity.isStreaming()); diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java b/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java index 65ee4bfccc..39b4c5d73d 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientConnectionRelease.java @@ -59,9 +59,9 @@ public final static void main(String[] args) throws Exception { // If the response does not enclose an entity, there is no need // to bother about connection release if (entity != null) { - InputStream instream = entity.getContent(); + InputStream inStream = entity.getContent(); try { - instream.read(); + inStream.read(); // do something useful with the response } catch (IOException ex) { // In case of an IOException the connection will be released @@ -69,7 +69,7 @@ public final static void main(String[] args) throws Exception { throw ex; } finally { // Closing the input stream will trigger connection release - instream.close(); + inStream.close(); } } } finally { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java index 93765e7eb1..6f5fc896b4 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/conn/BasicManagedEntity.java @@ -113,8 +113,8 @@ public void consumeContent() throws IOException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { - super.writeTo(outstream); + public void writeTo(final OutputStream outStream) throws IOException { + super.writeTo(outStream); ensureConsumed(); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java index 3e158ab23b..4a70effb5b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/BasicClientConnectionManager.java @@ -141,7 +141,7 @@ public void abortRequest() { @Override public ManagedClientConnection getConnection( - final long timeout, final TimeUnit tunit) { + final long timeout, final TimeUnit timeUnit) { return BasicClientConnectionManager.this.getConnection( route, state); } @@ -191,7 +191,7 @@ private void shutdownConnection(final HttpClientConnection conn) { } @Override - public void releaseConnection(final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) { + public void releaseConnection(final ManagedClientConnection conn, final long keepalive, final TimeUnit timeUnit) { Args.check(conn instanceof ManagedClientConnectionImpl, "Connection class mismatch, " + "connection not obtained from this manager"); final ManagedClientConnectionImpl managedConn = (ManagedClientConnectionImpl) conn; @@ -214,11 +214,11 @@ public void releaseConnection(final ManagedClientConnection conn, final long kee shutdownConnection(managedConn); } if (managedConn.isMarkedReusable()) { - this.poolEntry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS); + this.poolEntry.updateExpiry(keepalive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS); if (this.log.isDebugEnabled()) { final String s; if (keepalive > 0) { - s = "for " + keepalive + " " + tunit; + s = "for " + keepalive + " " + timeUnit; } else { s = "indefinitely"; } @@ -249,11 +249,11 @@ public void closeExpiredConnections() { } @Override - public void closeIdleConnections(final long idletime, final TimeUnit tunit) { - Args.notNull(tunit, "Time unit"); + public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { + Args.notNull(timeUnit, "Time unit"); synchronized (this) { assertNotShutdown(); - long time = tunit.toMillis(idletime); + long time = timeUnit.toMillis(idletime); if (time < 0) { time = 0; } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java index 081f0671c2..027a1f2d0b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/DefaultClientConnection.java @@ -187,29 +187,29 @@ public void close() throws IOException { @Override protected SessionInputBuffer createSessionInputBuffer( final Socket socket, - final int buffersize, + final int bufferSize, final HttpParams params) throws IOException { - SessionInputBuffer inbuffer = super.createSessionInputBuffer( + SessionInputBuffer inBuffer = super.createSessionInputBuffer( socket, - buffersize > 0 ? buffersize : 8192, + bufferSize > 0 ? bufferSize : 8192, params); if (wireLog.isDebugEnabled()) { - inbuffer = new LoggingSessionInputBuffer( - inbuffer, + inBuffer = new LoggingSessionInputBuffer( + inBuffer, new Wire(wireLog), HttpProtocolParams.getHttpElementCharset(params)); } - return inbuffer; + return inBuffer; } @Override protected SessionOutputBuffer createSessionOutputBuffer( final Socket socket, - final int buffersize, + final int bufferSize, final HttpParams params) throws IOException { SessionOutputBuffer outbuffer = super.createSessionOutputBuffer( socket, - buffersize > 0 ? buffersize : 8192, + bufferSize > 0 ? bufferSize : 8192, params); if (wireLog.isDebugEnabled()) { outbuffer = new LoggingSessionOutputBuffer( diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java index c89dbe402c..f9bf401144 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpConnPool.java @@ -49,22 +49,22 @@ class HttpConnPool extends AbstractConnPool { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpPoolEntry.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpPoolEntry.java index b39d9520ad..9a27688719 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpPoolEntry.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/HttpPoolEntry.java @@ -52,8 +52,8 @@ public HttpPoolEntry( final String id, final HttpRoute route, final OperatedClientConnection conn, - final long timeToLive, final TimeUnit tunit) { - super(id, route, conn, timeToLive, tunit); + final long timeToLive, final TimeUnit timeUnit) { + super(id, route, conn, timeToLive, timeUnit); this.log = log; this.tracker = new RouteTracker(route); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java index a0b37ae13d..6013a290a1 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/LoggingSessionInputBuffer.java @@ -83,29 +83,29 @@ public boolean isDataAvailable(final int timeout) throws IOException { @Override public int read(final byte[] b, final int off, final int len) throws IOException { - final int l = this.in.read(b, off, len); - if (this.wire.enabled() && l > 0) { - this.wire.input(b, off, l); + final int readLen = this.in.read(b, off, len); + if (this.wire.enabled() && readLen > 0) { + this.wire.input(b, off, readLen); } - return l; + return readLen; } @Override public int read() throws IOException { - final int l = this.in.read(); - if (this.wire.enabled() && l != -1) { - this.wire.input(l); + final int b = this.in.read(); + if (this.wire.enabled() && b != -1) { + this.wire.input(b); } - return l; + return b; } @Override public int read(final byte[] b) throws IOException { - final int l = this.in.read(b); - if (this.wire.enabled() && l > 0) { - this.wire.input(b, 0, l); + final int readLen = this.in.read(b); + if (this.wire.enabled() && readLen > 0) { + this.wire.input(b, 0, readLen); } - return l; + return readLen; } @Override @@ -120,14 +120,14 @@ public String readLine() throws IOException { @Override public int readLine(final CharArrayBuffer buffer) throws IOException { - final int l = this.in.readLine(buffer); - if (this.wire.enabled() && l >= 0) { - final int pos = buffer.length() - l; - final String s = new String(buffer.buffer(), pos, l); + final int readLen = this.in.readLine(buffer); + if (this.wire.enabled() && readLen >= 0) { + final int pos = buffer.length() - readLen; + final String s = new String(buffer.buffer(), pos, readLen); final String tmp = s + "\r\n"; this.wire.input(tmp.getBytes(this.charset)); } - return l; + return readLen; } @Override diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java index 3e2fefbbb4..57f3dc669b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/PoolingClientConnectionManager.java @@ -98,12 +98,12 @@ public PoolingClientConnectionManager() { public PoolingClientConnectionManager( final SchemeRegistry schemeRegistry, - final long timeToLive, final TimeUnit tunit) { - this(schemeRegistry, timeToLive, tunit, new SystemDefaultDnsResolver()); + final long timeToLive, final TimeUnit timeUnit) { + this(schemeRegistry, timeToLive, timeUnit, new SystemDefaultDnsResolver()); } public PoolingClientConnectionManager(final SchemeRegistry schemeRegistry, - final long timeToLive, final TimeUnit tunit, + final long timeToLive, final TimeUnit timeUnit, final DnsResolver dnsResolver) { super(); Args.notNull(schemeRegistry, "Scheme registry"); @@ -111,7 +111,7 @@ public PoolingClientConnectionManager(final SchemeRegistry schemeRegistry, this.schemeRegistry = schemeRegistry; this.dnsResolver = dnsResolver; this.operator = createConnectionOperator(schemeRegistry); - this.pool = new HttpConnPool(this.log, this.operator, 2, 20, timeToLive, tunit); + this.pool = new HttpConnPool(this.log, this.operator, 2, 20, timeToLive, timeUnit); } @Override @@ -196,8 +196,8 @@ public void abortRequest() { @Override public ManagedClientConnection getConnection( final long timeout, - final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException { - return leaseConnection(future, timeout, tunit); + final TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException { + return leaseConnection(future, timeout, timeUnit); } }; @@ -207,10 +207,10 @@ public ManagedClientConnection getConnection( ManagedClientConnection leaseConnection( final Future future, final long timeout, - final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException { + final TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException { final HttpPoolEntry entry; try { - entry = future.get(timeout, tunit); + entry = future.get(timeout, timeUnit); if (entry == null || future.isCancelled()) { throw new InterruptedException(); } @@ -234,7 +234,7 @@ ManagedClientConnection leaseConnection( @Override public void releaseConnection( - final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) { + final ManagedClientConnection conn, final long keepalive, final TimeUnit timeUnit) { Args.check(conn instanceof ManagedClientConnectionImpl, "Connection class mismatch, " + "connection not obtained from this manager"); @@ -257,11 +257,11 @@ public void releaseConnection( } // Only reusable connections can be kept alive if (managedConn.isMarkedReusable()) { - entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS); + entry.updateExpiry(keepalive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS); if (this.log.isDebugEnabled()) { final String s; if (keepalive > 0) { - s = "for " + keepalive + " " + tunit; + s = "for " + keepalive + " " + timeUnit; } else { s = "indefinitely"; } @@ -289,11 +289,11 @@ public void shutdown() { } @Override - public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { + public void closeIdleConnections(final long idleTimeout, final TimeUnit timeUnit) { if (this.log.isDebugEnabled()) { - this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); + this.log.debug("Closing connections idle longer than " + idleTimeout + " " + timeUnit); } - this.pool.closeIdle(idleTimeout, tunit); + this.pool.closeIdle(idleTimeout, timeUnit); } @Override diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java index 2861b9b690..993fa70754 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/SingleClientConnManager.java @@ -186,7 +186,7 @@ public void abortRequest() { @Override public ManagedClientConnection getConnection( - final long timeout, final TimeUnit tunit) { + final long timeout, final TimeUnit timeUnit) { return SingleClientConnManager.this.getConnection( route, state); } @@ -317,16 +317,16 @@ public void closeExpiredConnections() { } @Override - public void closeIdleConnections(final long idletime, final TimeUnit tunit) { + public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { assertStillUp(); // idletime can be 0 or negative, no problem there - Args.notNull(tunit, "Time unit"); + Args.notNull(timeUnit, "Time unit"); synchronized (this) { if ((managedConn == null) && uniquePoolEntry.connection.isOpen()) { final long cutoff = - System.currentTimeMillis() - tunit.toMillis(idletime); + System.currentTimeMillis() - timeUnit.toMillis(idletime); if (lastReleaseTime <= cutoff) { try { uniquePoolEntry.close(); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java index d9dfbfe2ba..f9fd51734b 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/AbstractConnPool.java @@ -99,7 +99,7 @@ public void enableConnectionGC() * @param route the route for which to get the connection * @param state the state * @param timeout the timeout, 0 or negative for no timeout - * @param tunit the unit for the {@code timeout}, + * @param timeUnit the unit for the {@code timeout}, * may be {@code null} only if there is no timeout * * @return pool entry holding a connection for the route @@ -114,9 +114,9 @@ BasicPoolEntry getEntry( final HttpRoute route, final Object state, final long timeout, - final TimeUnit tunit) + final TimeUnit timeUnit) throws ConnectionPoolTimeoutException, InterruptedException { - return requestPoolEntry(route, state).getPoolEntry(timeout, tunit); + return requestPoolEntry(route, state).getPoolEntry(timeout, timeUnit); } /** @@ -154,16 +154,16 @@ public void handleReference(final Reference ref) { * * @param idletime the time the connections should have been idle * in order to be closed now - * @param tunit the unit for the {@code idletime} + * @param timeUnit the unit for the {@code idletime} */ - public void closeIdleConnections(final long idletime, final TimeUnit tunit) { + public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { // idletime can be 0 or negative, no problem there - Args.notNull(tunit, "Time unit"); + Args.notNull(timeUnit, "Time unit"); poolLock.lock(); try { - idleConnHandler.closeIdleConnections(tunit.toMillis(idletime)); + idleConnHandler.closeIdleConnections(timeUnit.toMillis(idletime)); } finally { poolLock.unlock(); } diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java index 31914c47f5..07f4afd35c 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ConnPoolByRoute.java @@ -295,9 +295,9 @@ public void abortRequest() { @Override public BasicPoolEntry getPoolEntry( final long timeout, - final TimeUnit tunit) + final TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException { - return getEntryBlocking(route, state, timeout, tunit, aborter); + return getEntryBlocking(route, state, timeout, timeUnit, aborter); } }; @@ -310,7 +310,7 @@ public BasicPoolEntry getPoolEntry( * * @param route the route for which to get the connection * @param timeout the timeout, 0 or negative for no timeout - * @param tunit the unit for the {@code timeout}, + * @param timeUnit the unit for the {@code timeout}, * may be {@code null} only if there is no timeout * @param aborter an object which can abort a {@link WaitingThread}. * @@ -323,14 +323,14 @@ public BasicPoolEntry getPoolEntry( */ protected BasicPoolEntry getEntryBlocking( final HttpRoute route, final Object state, - final long timeout, final TimeUnit tunit, + final long timeout, final TimeUnit timeUnit, final WaitingThreadAborter aborter) throws ConnectionPoolTimeoutException, InterruptedException { Date deadline = null; if (timeout > 0) { deadline = new Date - (System.currentTimeMillis() + tunit.toMillis(timeout)); + (System.currentTimeMillis() + timeUnit.toMillis(timeout)); } BasicPoolEntry entry = null; @@ -710,17 +710,17 @@ public void deleteClosedConnections() { * * @param idletime the time the connections should have been idle * in order to be closed now - * @param tunit the unit for the {@code idletime} + * @param timeUnit the unit for the {@code idletime} */ @Override - public void closeIdleConnections(final long idletime, final TimeUnit tunit) { - Args.notNull(tunit, "Time unit"); + public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { + Args.notNull(timeUnit, "Time unit"); final long t = idletime > 0 ? idletime : 0; if (log.isDebugEnabled()) { - log.debug("Closing connections idle longer than " + t + " " + tunit); + log.debug("Closing connections idle longer than " + t + " " + timeUnit); } // the latest time for which connections will be closed - final long deadline = System.currentTimeMillis() - tunit.toMillis(t); + final long deadline = System.currentTimeMillis() - timeUnit.toMillis(t); poolLock.lock(); try { final Iterator iter = freeConnections.iterator(); diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/PoolEntryRequest.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/PoolEntryRequest.java index 52b3564301..50908889e5 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/PoolEntryRequest.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/PoolEntryRequest.java @@ -46,7 +46,7 @@ public interface PoolEntryRequest { * an {@link InterruptedException} is thrown. * * @param timeout the timeout, 0 or negative for no timeout - * @param tunit the unit for the {@code timeout}, + * @param timeUnit the unit for the {@code timeout}, * may be {@code null} only if there is no timeout * * @return pool entry holding a connection for the route @@ -58,7 +58,7 @@ public interface PoolEntryRequest { */ BasicPoolEntry getPoolEntry( long timeout, - TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException; + TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException; /** * Aborts the active or next call to diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java index 74f11189c4..dd2147a34e 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java @@ -232,7 +232,7 @@ public void abortRequest() { @Override public ManagedClientConnection getConnection( - final long timeout, final TimeUnit tunit) throws InterruptedException, + final long timeout, final TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException { Args.notNull(route, "Route"); @@ -240,7 +240,7 @@ public ManagedClientConnection getConnection( log.debug("Get connection: " + route + ", timeout = " + timeout); } - final BasicPoolEntry entry = poolRequest.getPoolEntry(timeout, tunit); + final BasicPoolEntry entry = poolRequest.getPoolEntry(timeout, timeUnit); return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry); } @@ -327,11 +327,11 @@ public int getConnectionsInPool() { } @Override - public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { + public void closeIdleConnections(final long idleTimeout, final TimeUnit timeUnit) { if (log.isDebugEnabled()) { - log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); + log.debug("Closing connections idle longer than " + idleTimeout + " " + timeUnit); } - pool.closeIdleConnections(idleTimeout, tunit); + pool.closeIdleConnections(idleTimeout, timeUnit); } @Override diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java b/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java index 30a578eee4..8e7f0e9fa9 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthSchemeRegistry.java @@ -112,9 +112,8 @@ public AuthScheme getAuthScheme(final String name, final HttpParams params) final AuthSchemeFactory factory = registeredSchemes.get(name.toLowerCase(Locale.ENGLISH)); if (factory != null) { return factory.newInstance(params); - } else { - throw new IllegalStateException("Unsupported authentication scheme: " + name); } + throw new IllegalStateException("Unsupported authentication scheme: " + name); } /** diff --git a/httpclient/src/main/java/org/apache/http/client/entity/DecompressingEntity.java b/httpclient/src/main/java/org/apache/http/client/entity/DecompressingEntity.java index 08d7c6d279..27ee00d48b 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/DecompressingEntity.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/DecompressingEntity.java @@ -79,23 +79,22 @@ public InputStream getContent() throws IOException { content = getDecompressingStream(); } return content; - } else { - return getDecompressingStream(); } + return getDecompressingStream(); } @Override - public void writeTo(final OutputStream outstream) throws IOException { - Args.notNull(outstream, "Output stream"); - final InputStream instream = getContent(); + public void writeTo(final OutputStream outStream) throws IOException { + Args.notNull(outStream, "Output stream"); + final InputStream inStream = getContent(); try { final byte[] buffer = new byte[BUFFER_SIZE]; int l; - while ((l = instream.read(buffer)) != -1) { - outstream.write(buffer, 0, l); + while ((l = inStream.read(buffer)) != -1) { + outStream.write(buffer, 0, l); } } finally { - instream.close(); + inStream.close(); } } diff --git a/httpclient/src/main/java/org/apache/http/client/entity/GzipCompressingEntity.java b/httpclient/src/main/java/org/apache/http/client/entity/GzipCompressingEntity.java index 30082398f8..cfa45df9ad 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/GzipCompressingEntity.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/GzipCompressingEntity.java @@ -101,9 +101,9 @@ public InputStream getContent() throws IOException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { - Args.notNull(outstream, "Output stream"); - final GZIPOutputStream gzip = new GZIPOutputStream(outstream); + public void writeTo(final OutputStream outStream) throws IOException { + Args.notNull(outStream, "Output stream"); + final GZIPOutputStream gzip = new GZIPOutputStream(outStream); wrappedEntity.writeTo(gzip); // Only close output stream if the wrapped entity has been // successfully written out diff --git a/httpclient/src/main/java/org/apache/http/client/entity/InputStreamFactory.java b/httpclient/src/main/java/org/apache/http/client/entity/InputStreamFactory.java index 4753cf602e..56d99d6bf0 100644 --- a/httpclient/src/main/java/org/apache/http/client/entity/InputStreamFactory.java +++ b/httpclient/src/main/java/org/apache/http/client/entity/InputStreamFactory.java @@ -36,6 +36,6 @@ */ public interface InputStreamFactory { - InputStream create(InputStream instream) throws IOException; + InputStream create(InputStream inStream) throws IOException; } diff --git a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java index dbfbd0e14d..c52ece50c8 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/HttpRequestWrapper.java @@ -189,11 +189,10 @@ public static HttpRequestWrapper wrap(final HttpRequest request) { */ public static HttpRequestWrapper wrap(final HttpRequest request, final HttpHost target) { Args.notNull(request, "HTTP request"); - if (request instanceof HttpEntityEnclosingRequest) { - return new HttpEntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request, target); - } else { - return new HttpRequestWrapper(request, target); - } + return request instanceof HttpEntityEnclosingRequest + ? new HttpEntityEnclosingRequestWrapper( + (HttpEntityEnclosingRequest) request, target) + : new HttpRequestWrapper(request, target); } /** diff --git a/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java b/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java index e763e9a705..e815d8aeb3 100644 --- a/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java +++ b/httpclient/src/main/java/org/apache/http/client/protocol/HttpClientContext.java @@ -134,11 +134,9 @@ public class HttpClientContext extends HttpCoreContext { public static final String REQUEST_CONFIG = "http.request-config"; public static HttpClientContext adapt(final HttpContext context) { - if (context instanceof HttpClientContext) { - return (HttpClientContext) context; - } else { - return new HttpClientContext(context); - } + return context instanceof HttpClientContext + ? (HttpClientContext) context + : new HttpClientContext(context); } public static HttpClientContext create() { diff --git a/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java index be8e56d7cf..ed2db741f4 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/CloneUtils.java @@ -59,15 +59,13 @@ public static T cloneObject(final T obj) throws CloneNotSupportedException { final Throwable cause = ex.getCause(); if (cause instanceof CloneNotSupportedException) { throw ((CloneNotSupportedException) cause); - } else { - throw new Error("Unexpected exception", cause); } + throw new Error("Unexpected exception", cause); } catch (final IllegalAccessException ex) { throw new IllegalAccessError(ex.getMessage()); } - } else { - throw new CloneNotSupportedException(); } + throw new CloneNotSupportedException(); } public static Object clone(final Object obj) throws CloneNotSupportedException { diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java index 0a79b4a1ea..35c74de0ae 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIBuilder.java @@ -495,11 +495,9 @@ public String getPath() { } public List getQueryParams() { - if (this.queryParams != null) { - return new ArrayList(this.queryParams); - } else { - return new ArrayList(); - } + return this.queryParams != null + ? new ArrayList(this.queryParams) + : new ArrayList(); } public String getFragment() { diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java index 02f8c1ae93..7bb01c6e75 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java @@ -211,20 +211,12 @@ public static URI rewriteURIForRoute(final URI uri, final RouteInfo route) throw } if (route.getProxyHost() != null && !route.isTunnelled()) { // Make sure the request URI is absolute - if (!uri.isAbsolute()) { - final HttpHost target = route.getTargetHost(); - return rewriteURI(uri, target, true); - } else { - return rewriteURI(uri); - } - } else { - // Make sure the request URI is relative - if (uri.isAbsolute()) { - return rewriteURI(uri, null, true); - } else { - return rewriteURI(uri); - } + return uri.isAbsolute() + ? rewriteURI(uri) + : rewriteURI(uri, route.getTargetHost(), true); } + // Make sure the request URI is relative + return uri.isAbsolute() ? rewriteURI(uri, null, true) : rewriteURI(uri); } /** diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index d85cf8d654..0397cc4f2d 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -124,14 +124,14 @@ public static List parse( final long len = entity.getContentLength(); Args.check(len <= Integer.MAX_VALUE, "HTTP entity is too large"); final Charset charset = contentType.getCharset() != null ? contentType.getCharset() : HTTP.DEF_CONTENT_CHARSET; - final InputStream instream = entity.getContent(); - if (instream == null) { + final InputStream inStream = entity.getContent(); + if (inStream == null) { return createEmptyList(); } final CharArrayBuffer buf; try { buf = new CharArrayBuffer(len > 0 ? (int) len : 1024); - final Reader reader = new InputStreamReader(instream, charset); + final Reader reader = new InputStreamReader(inStream, charset); final char[] tmp = new char[1024]; int l; while((l = reader.read(tmp)) != -1) { @@ -139,7 +139,7 @@ public static List parse( } } finally { - instream.close(); + inStream.close(); } if (buf.isEmpty()) { return createEmptyList(); diff --git a/httpclient/src/main/java/org/apache/http/conn/ClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/conn/ClientConnectionManager.java index 8b30e68fa6..845507c27b 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/conn/ClientConnectionManager.java @@ -92,11 +92,11 @@ public interface ClientConnectionManager { * All expired connections will also be closed. * * @param idletime the idle time of connections to be closed - * @param tunit the unit for the {@code idletime} + * @param timeUnit the unit for the {@code idletime} * * @see #closeExpiredConnections() */ - void closeIdleConnections(long idletime, TimeUnit tunit); + void closeIdleConnections(long idletime, TimeUnit timeUnit); /** * Closes all expired connections in the pool. diff --git a/httpclient/src/main/java/org/apache/http/conn/ClientConnectionRequest.java b/httpclient/src/main/java/org/apache/http/conn/ClientConnectionRequest.java index cd8d5c4395..afb053ea04 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ClientConnectionRequest.java +++ b/httpclient/src/main/java/org/apache/http/conn/ClientConnectionRequest.java @@ -51,7 +51,7 @@ public interface ClientConnectionRequest { * be thrown. * * @param timeout the timeout, 0 or negative for no timeout - * @param tunit the unit for the {@code timeout}, + * @param timeUnit the unit for the {@code timeout}, * may be {@code null} only if there is no timeout * * @return a connection that can be used to communicate @@ -62,7 +62,7 @@ public interface ClientConnectionRequest { * @throws InterruptedException * if the calling thread is interrupted while waiting */ - ManagedClientConnection getConnection(long timeout, TimeUnit tunit) + ManagedClientConnection getConnection(long timeout, TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException; /** diff --git a/httpclient/src/main/java/org/apache/http/conn/ConnectionRequest.java b/httpclient/src/main/java/org/apache/http/conn/ConnectionRequest.java index 3520a52d60..ccd9eb3882 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ConnectionRequest.java +++ b/httpclient/src/main/java/org/apache/http/conn/ConnectionRequest.java @@ -52,7 +52,7 @@ public interface ConnectionRequest extends Cancellable { * be thrown. * * @param timeout the timeout, 0 or negative for no timeout - * @param tunit the unit for the {@code timeout}, + * @param timeUnit the unit for the {@code timeout}, * may be {@code null} only if there is no timeout * * @return a connection that can be used to communicate @@ -63,7 +63,7 @@ public interface ConnectionRequest extends Cancellable { * @throws InterruptedException * if the calling thread is interrupted while waiting */ - HttpClientConnection get(long timeout, TimeUnit tunit) + HttpClientConnection get(long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException; } diff --git a/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java b/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java index fb7de2d6ba..774c65baf3 100644 --- a/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java +++ b/httpclient/src/main/java/org/apache/http/conn/EofSensorInputStream.java @@ -111,36 +111,36 @@ protected boolean isReadAllowed() throws IOException { @Override public int read() throws IOException { - int l = -1; + int readLen = -1; if (isReadAllowed()) { try { - l = wrappedStream.read(); - checkEOF(l); + readLen = wrappedStream.read(); + checkEOF(readLen); } catch (final IOException ex) { checkAbort(); throw ex; } } - return l; + return readLen; } @Override public int read(final byte[] b, final int off, final int len) throws IOException { - int l = -1; + int readLen = -1; if (isReadAllowed()) { try { - l = wrappedStream.read(b, off, len); - checkEOF(l); + readLen = wrappedStream.read(b, off, len); + checkEOF(readLen); } catch (final IOException ex) { checkAbort(); throw ex; } } - return l; + return readLen; } @Override diff --git a/httpclient/src/main/java/org/apache/http/conn/HttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/conn/HttpClientConnectionManager.java index 70c290817d..d39f17968d 100644 --- a/httpclient/src/main/java/org/apache/http/conn/HttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/conn/HttpClientConnectionManager.java @@ -155,11 +155,11 @@ void routeComplete( *

          * * @param idletime the idle time of connections to be closed - * @param tunit the unit for the {@code idletime} + * @param timeUnit the unit for the {@code idletime} * * @see #closeExpiredConnections() */ - void closeIdleConnections(long idletime, TimeUnit tunit); + void closeIdleConnections(long idletime, TimeUnit timeUnit); /** * Closes all expired connections in the pool. diff --git a/httpclient/src/main/java/org/apache/http/conn/ManagedClientConnection.java b/httpclient/src/main/java/org/apache/http/conn/ManagedClientConnection.java index 8a067976f2..2d5384e2fb 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ManagedClientConnection.java +++ b/httpclient/src/main/java/org/apache/http/conn/ManagedClientConnection.java @@ -32,7 +32,6 @@ import javax.net.ssl.SSLSession; -import org.apache.http.HttpClientConnection; import org.apache.http.HttpHost; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.params.HttpParams; @@ -48,7 +47,7 @@ */ @Deprecated public interface ManagedClientConnection extends - HttpClientConnection, HttpRoutedConnection, ManagedHttpClientConnection, ConnectionReleaseTrigger { + HttpRoutedConnection, ManagedHttpClientConnection, ConnectionReleaseTrigger { /** * Indicates whether this connection is secure. diff --git a/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java b/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java index 60a02e7265..bf843da0d6 100644 --- a/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java +++ b/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java @@ -103,16 +103,13 @@ private static int getDefaultPort(final String schemeName) { private static HttpHost normalize(final HttpHost target) { if (target.getPort() >= 0 ) { return target; - } else { - final InetAddress address = target.getAddress(); - final String schemeName = target.getSchemeName(); - if (address != null) { - return new HttpHost(address, getDefaultPort(schemeName), schemeName); - } else { - final String hostName = target.getHostName(); - return new HttpHost(hostName, getDefaultPort(schemeName), schemeName); - } } + final InetAddress address = target.getAddress(); + final String schemeName = target.getSchemeName(); + return address != null + ? new HttpHost(address, getDefaultPort(schemeName), schemeName) + : new HttpHost(target.getHostName(), getDefaultPort(schemeName), + schemeName); } /** @@ -238,11 +235,7 @@ public final HttpHost getHopTarget(final int hop) { Args.notNegative(hop, "Hop index"); final int hopcount = getHopCount(); Args.check(hop < hopcount, "Hop index exceeds tracked route length"); - if (hop < hopcount - 1) { - return this.proxyChain.get(hop); - } else { - return this.targetHost; - } + return hop < hopcount - 1 ? this.proxyChain.get(hop) : this.targetHost; } @Override @@ -298,9 +291,8 @@ public final boolean equals(final Object obj) { LangUtils.equals(this.targetHost, that.targetHost) && LangUtils.equals(this.localAddress, that.localAddress) && LangUtils.equals(this.proxyChain, that.proxyChain); - } else { - return false; } + return false; } diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java b/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java index 6d02b95fe4..3201710392 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/Scheme.java @@ -163,14 +163,11 @@ public final int getDefaultPort() { public final SocketFactory getSocketFactory() { if (this.socketFactory instanceof SchemeSocketFactoryAdaptor) { return ((SchemeSocketFactoryAdaptor) this.socketFactory).getFactory(); - } else { - if (this.layered) { - return new LayeredSocketFactoryAdaptor( - (LayeredSchemeSocketFactory) this.socketFactory); - } else { - return new SocketFactoryAdaptor(this.socketFactory); - } } + return this.layered + ? new LayeredSocketFactoryAdaptor( + (LayeredSchemeSocketFactory) this.socketFactory) + : new SocketFactoryAdaptor(this.socketFactory); } /** @@ -245,9 +242,8 @@ public final boolean equals(final Object obj) { return this.name.equals(that.name) && this.defaultPort == that.defaultPort && this.layered == that.layered; - } else { - return false; } + return false; } @Override diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactoryAdaptor.java b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactoryAdaptor.java index 08de43e5cf..049145d748 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactoryAdaptor.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactoryAdaptor.java @@ -88,11 +88,9 @@ public boolean equals(final Object obj) { if (this == obj) { return true; } - if (obj instanceof SchemeSocketFactoryAdaptor) { - return this.factory.equals(((SchemeSocketFactoryAdaptor)obj).factory); - } else { - return this.factory.equals(obj); - } + return obj instanceof SchemeSocketFactoryAdaptor + ? this.factory.equals(((SchemeSocketFactoryAdaptor) obj).factory) + : this.factory.equals(obj); } @Override diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java b/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java index 3a9f9a0242..65a160b9b3 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java @@ -85,11 +85,9 @@ public boolean equals(final Object obj) { if (this == obj) { return true; } - if (obj instanceof SocketFactoryAdaptor) { - return this.factory.equals(((SocketFactoryAdaptor)obj).factory); - } else { - return this.factory.equals(obj); - } + return obj instanceof SocketFactoryAdaptor + ? this.factory.equals(((SocketFactoryAdaptor) obj).factory) + : this.factory.equals(obj); } @Override diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java index ec7c0bfe14..4877b30372 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -214,9 +214,8 @@ private static boolean matchIdentity(final String host, final String identity, f match = normalizedHost.endsWith(normalizedIdentity.substring(1)); } return match && (!strict || countDots(normalizedHost) == countDots(normalizedIdentity)); - } else { - return normalizedHost.equals(normalizedIdentity); } + return normalizedHost.equals(normalizedIdentity); } private static boolean validCountryWildcard(final String parts[]) { diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java index e7f9b28ea3..6ec4412f96 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java @@ -351,9 +351,8 @@ public Socket connectSocket( sslsock.startHandshake(); verifyHostname(sslsock, host.getHostName()); return sock; - } else { - return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context); } + return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context); } @Override diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java index ce2a2c901f..e069370549 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java @@ -103,11 +103,7 @@ private static boolean hasEntry(final Map map, final String return false; } final DomainType domainType = map.get(rule); - if (domainType == null) { - return false; - } else { - return expectedType == null || domainType.equals(expectedType); - } + return domainType == null ? false : expectedType == null || domainType.equals(expectedType); } private boolean hasRule(final String rule, final DomainType expectedType) { diff --git a/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java b/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java index e24be611f3..4407f130dc 100644 --- a/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java +++ b/httpclient/src/main/java/org/apache/http/cookie/CookieSpecRegistry.java @@ -107,9 +107,8 @@ public CookieSpec getCookieSpec(final String name, final HttpParams params) final CookieSpecFactory factory = registeredSpecs.get(name.toLowerCase(Locale.ENGLISH)); if (factory != null) { return factory.newInstance(params); - } else { - throw new IllegalStateException("Unsupported cookie spec: " + name); } + throw new IllegalStateException("Unsupported cookie spec: " + name); } /** diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java index 296b15c34e..a1515dfd69 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java @@ -159,11 +159,7 @@ public ChallengeState getChallengeState() { @Override public String toString() { final String name = getSchemeName(); - if (name != null) { - return name.toUpperCase(Locale.ROOT); - } else { - return super.toString(); - } + return name != null ? name.toUpperCase(Locale.ROOT) : super.toString(); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java index 1e3c62f415..74d0377cad 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java @@ -152,11 +152,7 @@ public void processChallenge( @Override public boolean isComplete() { final String s = getParameter("stale"); - if ("true".equalsIgnoreCase(s)) { - return false; - } else { - return this.complete; - } + return "true".equalsIgnoreCase(s) ? false : this.complete; } /** diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java index 1fbc86a14e..e341a8545c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java @@ -120,11 +120,9 @@ protected byte[] generateGSSToken( } final GSSContext gssContext = createGSSContext(manager, oid, serverName, gssCredential); - if (input != null) { - return gssContext.initSecContext(input, 0, input.length); - } else { - return gssContext.initSecContext(new byte[] {}, 0, 0); - } + return input != null + ? gssContext.initSecContext(input, 0, input.length) + : gssContext.initSecContext(new byte[] {}, 0, 0); } GSSContext createGSSContext( diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/HttpAuthenticator.java b/httpclient/src/main/java/org/apache/http/impl/auth/HttpAuthenticator.java index 6bc28783e0..a19bd48179 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/HttpAuthenticator.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/HttpAuthenticator.java @@ -79,21 +79,20 @@ public boolean isAuthenticationRequested( authStrategy.authFailed(host, authState.getAuthScheme(), context); } return true; - } else { - switch (authState.getState()) { - case CHALLENGED: - case HANDSHAKE: - this.log.debug("Authentication succeeded"); - authState.setState(AuthProtocolState.SUCCESS); - authStrategy.authSucceeded(host, authState.getAuthScheme(), context); - break; - case SUCCESS: - break; - default: - authState.setState(AuthProtocolState.UNCHALLENGED); - } - return false; } + switch (authState.getState()) { + case CHALLENGED: + case HANDSHAKE: + this.log.debug("Authentication succeeded"); + authState.setState(AuthProtocolState.SUCCESS); + authStrategy.authSucceeded(host, authState.getAuthScheme(), context); + break; + case SUCCESS: + break; + default: + authState.setState(AuthProtocolState.UNCHALLENGED); + } + return false; } public boolean handleAuthChallenge( @@ -141,14 +140,12 @@ public boolean handleAuthChallenge( authState.reset(); authState.setState(AuthProtocolState.FAILURE); return false; - } else { - authState.setState(AuthProtocolState.HANDSHAKE); - return true; } - } else { - authState.reset(); - // Retry authentication with a different scheme + authState.setState(AuthProtocolState.HANDSHAKE); + return true; } + authState.reset(); + // Retry authentication with a different scheme } } final Queue authOptions = authStrategy.select(challenges, host, response, context); @@ -159,9 +156,8 @@ public boolean handleAuthChallenge( authState.setState(AuthProtocolState.CHALLENGED); authState.update(authOptions); return true; - } else { - return false; } + return false; } catch (final MalformedChallengeException ex) { if (this.log.isWarnEnabled()) { this.log.warn("Malformed challenge: " + ex.getMessage()); @@ -209,9 +205,8 @@ public void generateAuthResponse( } } return; - } else { - ensureAuthScheme(authScheme); } + ensureAuthScheme(authScheme); } if (authScheme != null) { try { @@ -235,11 +230,10 @@ private Header doAuth( final Credentials creds, final HttpRequest request, final HttpContext context) throws AuthenticationException { - if (authScheme instanceof ContextAwareAuthScheme) { - return ((ContextAwareAuthScheme) authScheme).authenticate(creds, request, context); - } else { - return authScheme.authenticate(creds, request); - } + return authScheme instanceof ContextAwareAuthScheme + ? ((ContextAwareAuthScheme) authScheme).authenticate(creds, request, + context) + : authScheme.authenticate(creds, request); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index 1677e777e3..e642615e27 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -209,7 +209,7 @@ static String getType3Message(final String user, final String password, final St targetInformation, peerServerCertificate, type1Message, type2Message).getResponse(); } - private static int readULong(final byte[] src, final int index) throws NTLMEngineException { + private static int readULong(final byte[] src, final int index) { if (src.length < index + 4) { return 0; } @@ -217,14 +217,14 @@ private static int readULong(final byte[] src, final int index) throws NTLMEngin | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); } - private static int readUShort(final byte[] src, final int index) throws NTLMEngineException { + private static int readUShort(final byte[] src, final int index) { if (src.length < index + 2) { return 0; } return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); } - private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException { + private static byte[] readSecurityBuffer(final byte[] src, final int index) { final int length = readUShort(src, index); final int offset = readULong(src, index + 4); if (src.length < offset + length) { @@ -236,7 +236,7 @@ private static byte[] readSecurityBuffer(final byte[] src, final int index) thro } /** Calculate a challenge block */ - private static byte[] makeRandomChallenge(final Random random) throws NTLMEngineException { + private static byte[] makeRandomChallenge(final Random random) { final byte[] rval = new byte[8]; synchronized (random) { random.nextBytes(rval); @@ -245,7 +245,7 @@ private static byte[] makeRandomChallenge(final Random random) throws NTLMEngine } /** Calculate a 16-byte secondary key */ - private static byte[] makeSecondaryKey(final Random random) throws NTLMEngineException { + private static byte[] makeSecondaryKey(final Random random) { final byte[] rval = new byte[16]; synchronized (random) { random.nextBytes(rval); @@ -747,8 +747,7 @@ private static byte[] lmResponse(final byte[] hash, final byte[] challenge) thro * @return The response (either NTLMv2 or LMv2, depending on the client * data). */ - private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData) - throws NTLMEngineException { + private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData) { final HMACMD5 hmacMD5 = new HMACMD5(hash); hmacMD5.update(challenge); hmacMD5.update(clientData); @@ -856,17 +855,17 @@ private void advanceMessageSequence() throws NTLMEngineException sequenceNumber++; } - private byte[] encrypt( final byte[] data ) throws NTLMEngineException + private byte[] encrypt( final byte[] data ) { return rc4.update( data ); } - private byte[] decrypt( final byte[] data ) throws NTLMEngineException + private byte[] decrypt( final byte[] data ) { return rc4.update( data ); } - private byte[] computeSignature( final byte[] message ) throws NTLMEngineException + private byte[] computeSignature( final byte[] message ) { final byte[] sig = new byte[16]; @@ -892,7 +891,7 @@ private byte[] computeSignature( final byte[] message ) throws NTLMEngineExcepti return sig; } - private boolean validateSignature( final byte[] signature, final byte message[] ) throws NTLMEngineException + private boolean validateSignature( final byte[] signature, final byte message[] ) { final byte[] computedSignature = computeSignature( message ); // log.info( "SSSSS validateSignature("+seqNumber+")\n" @@ -1036,12 +1035,11 @@ private static Charset getCharset(final int flags) throws NTLMEngineException { if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) { return DEFAULT_CHARSET; - } else { - if (UNICODE_LITTLE_UNMARKED == null) { - throw new NTLMEngineException( "Unicode not supported" ); - } - return UNICODE_LITTLE_UNMARKED; } + if (UNICODE_LITTLE_UNMARKED == null) { + throw new NTLMEngineException( "Unicode not supported" ); + } + return UNICODE_LITTLE_UNMARKED; } /** Strip dot suffix from a name */ diff --git a/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java b/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java index 4d163bae53..eeffd01a6a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/BasicAuthCache.java @@ -90,9 +90,8 @@ protected HttpHost getKey(final HttpHost host) { return host; } return new HttpHost(host.getHostName(), port, host.getSchemeName()); - } else { - return host; } + return host; } @Override @@ -142,9 +141,8 @@ public AuthScheme get(final HttpHost host) { } return null; } - } else { - return null; } + return null; } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java index dd5eb4a850..33ecf977e3 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultHttpRequestRetryHandler.java @@ -138,11 +138,10 @@ public boolean retryRequest( } if (this.nonRetriableClasses.contains(exception.getClass())) { return false; - } else { - for (final Class rejectException : this.nonRetriableClasses) { - if (rejectException.isInstance(exception)) { - return false; - } + } + for (final Class rejectException : this.nonRetriableClasses) { + if (rejectException.isInstance(exception)) { + return false; } } final HttpClientContext clientContext = HttpClientContext.adapt(context); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java index 0e02b2989a..5d92e5aafe 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategy.java @@ -226,11 +226,9 @@ public HttpUriRequest getRedirect( return new HttpGet(uri); } else { final int status = response.getStatusLine().getStatusCode(); - if (status == HttpStatus.SC_TEMPORARY_REDIRECT) { - return RequestBuilder.copy(request).setUri(uri).build(); - } else { - return new HttpGet(uri); - } + return status == HttpStatus.SC_TEMPORARY_REDIRECT + ? RequestBuilder.copy(request).setUri(uri).build() + : new HttpGet(uri); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java b/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java index 061ae3f5c8..8b099af546 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/EntityEnclosingRequestWrapper.java @@ -105,9 +105,9 @@ public InputStream getContent() throws IOException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { + public void writeTo(final OutputStream outStream) throws IOException { consumed = true; - super.writeTo(outstream); + super.writeTo(outStream); } } diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestFutureTask.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestFutureTask.java index f37cd7a918..1bd8090337 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestFutureTask.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestFutureTask.java @@ -82,9 +82,8 @@ public long startedTime() { public long endedTime() { if (isDone()) { return callable.getEnded(); - } else { - throw new IllegalStateException("Task is not done yet"); } + throw new IllegalStateException("Task is not done yet"); } /** @@ -94,9 +93,8 @@ public long endedTime() { public long requestDuration() { if (isDone()) { return endedTime() - startedTime(); - } else { - throw new IllegalStateException("Task is not done yet"); } + throw new IllegalStateException("Task is not done yet"); } /** @@ -105,9 +103,8 @@ public long requestDuration() { public long taskDuration() { if (isDone()) { return endedTime() - scheduledTime(); - } else { - throw new IllegalStateException("Task is not done yet"); } + throw new IllegalStateException("Task is not done yet"); } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestTaskCallable.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestTaskCallable.java index 47fb238031..749ac7e645 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestTaskCallable.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpRequestTaskCallable.java @@ -106,9 +106,8 @@ public V call() throws Exception { metrics.getTasks().increment(started); metrics.getActiveConnections().decrementAndGet(); } - } else { - throw new IllegalStateException("call has been cancelled for request " + request.getURI()); } + throw new IllegalStateException("call has been cancelled for request " + request.getURI()); } public void cancel() { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java b/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java index b95b5083b9..40c0ff4c1d 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/IdleConnectionEvictor.java @@ -104,8 +104,8 @@ public boolean isRunning() { return thread.isAlive(); } - public void awaitTermination(final long time, final TimeUnit tunit) throws InterruptedException { - thread.join((tunit != null ? tunit : TimeUnit.MILLISECONDS).toMillis(time)); + public void awaitTermination(final long time, final TimeUnit timeUnit) throws InterruptedException { + thread.join((timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS).toMillis(time)); } static class DefaultThreadFactory implements ThreadFactory { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java index 20bf060529..07eac49f12 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/InternalHttpClient.java @@ -240,8 +240,8 @@ public SchemeRegistry getSchemeRegistry() { } @Override - public void closeIdleConnections(final long idletime, final TimeUnit tunit) { - connManager.closeIdleConnections(idletime, tunit); + public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { + connManager.closeIdleConnections(idletime, timeUnit); } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java index 30ce492717..585eb9ea2b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/MinimalHttpClient.java @@ -150,8 +150,8 @@ public SchemeRegistry getSchemeRegistry() { } @Override - public void closeIdleConnections(final long idletime, final TimeUnit tunit) { - connManager.closeIdleConnections(idletime, tunit); + public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { + connManager.closeIdleConnections(idletime, timeUnit); } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index 122a85995c..3ac37f6a57 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -142,19 +142,13 @@ public Credentials getCredentials(final AuthScope authscope) { systemcreds.getUserName(), new String(systemcreds.getPassword()), null, domain); - } else { - if (AuthSchemes.NTLM.equalsIgnoreCase(authscope.getScheme())) { - // Domain may be specified in a fully qualified user name - return new NTCredentials( - systemcreds.getUserName(), - new String(systemcreds.getPassword()), - null, null); - } else { - return new UsernamePasswordCredentials( - systemcreds.getUserName(), - new String(systemcreds.getPassword())); - } } + return AuthSchemes.NTLM.equalsIgnoreCase(authscope.getScheme()) + // Domain may be specified in a fully qualified user name + ? new NTCredentials(systemcreds.getUserName(), + new String(systemcreds.getPassword()), null, null) + : new UsernamePasswordCredentials(systemcreds.getUserName(), + new String(systemcreds.getPassword())); } } return null; diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java index 10aef9f34d..811910207e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/BasicHttpClientConnectionManager.java @@ -200,7 +200,7 @@ public boolean cancel() { } @Override - public HttpClientConnection get(final long timeout, final TimeUnit tunit) { + public HttpClientConnection get(final long timeout, final TimeUnit timeUnit) { return BasicHttpClientConnectionManager.this.getConnection( route, state); } @@ -255,7 +255,7 @@ synchronized HttpClientConnection getConnection(final HttpRoute route, final Obj public synchronized void releaseConnection( final HttpClientConnection conn, final Object state, - final long keepalive, final TimeUnit tunit) { + final long keepalive, final TimeUnit timeUnit) { Args.notNull(conn, "Connection"); Asserts.check(conn == this.conn, "Connection not obtained from this manager"); if (this.log.isDebugEnabled()) { @@ -277,14 +277,14 @@ public synchronized void releaseConnection( if (this.log.isDebugEnabled()) { final String s; if (keepalive > 0) { - s = "for " + keepalive + " " + tunit; + s = "for " + keepalive + " " + timeUnit; } else { s = "indefinitely"; } this.log.debug("Connection can be kept alive " + s); } if (keepalive > 0) { - this.expiry = this.updated + tunit.toMillis(keepalive); + this.expiry = this.updated + timeUnit.toMillis(keepalive); } else { this.expiry = Long.MAX_VALUE; } @@ -343,13 +343,13 @@ public synchronized void closeExpiredConnections() { } @Override - public synchronized void closeIdleConnections(final long idletime, final TimeUnit tunit) { - Args.notNull(tunit, "Time unit"); + public synchronized void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { + Args.notNull(timeUnit, "Time unit"); if (this.isShutdown.get()) { return; } if (!this.leased) { - long time = tunit.toMillis(idletime); + long time = timeUnit.toMillis(idletime); if (time < 0) { time = 0; } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java b/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java index eee9b78d7b..603fd72f56 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java @@ -49,21 +49,21 @@ class CPool extends AbstractConnPool connFactory, final int defaultMaxPerRoute, final int maxTotal, - final long timeToLive, final TimeUnit tunit) { + final long timeToLive, final TimeUnit timeUnit) { super(connFactory, defaultMaxPerRoute, maxTotal); this.timeToLive = timeToLive; - this.tunit = tunit; + this.timeUnit = timeUnit; } @Override protected CPoolEntry createEntry(final HttpRoute route, final ManagedHttpClientConnection conn) { final String id = Long.toString(COUNTER.getAndIncrement()); - return new CPoolEntry(this.log, id, route, conn, this.timeToLive, this.tunit); + return new CPoolEntry(this.log, id, route, conn, this.timeToLive, this.timeUnit); } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java index cb89d27c74..bf122c8690 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolEntry.java @@ -52,8 +52,8 @@ public CPoolEntry( final String id, final HttpRoute route, final ManagedHttpClientConnection conn, - final long timeToLive, final TimeUnit tunit) { - super(id, route, conn, timeToLive, tunit); + final long timeToLive, final TimeUnit timeUnit) { + super(id, route, conn, timeToLive, timeUnit); this.log = log; } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java index 8c8f623da8..23197c29f1 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/CPoolProxy.java @@ -98,21 +98,13 @@ public void shutdown() throws IOException { @Override public boolean isOpen() { final CPoolEntry local = this.poolEntry; - if (local != null) { - return !local.isClosed(); - } else { - return false; - } + return local != null ? !local.isClosed() : false; } @Override public boolean isStale() { final HttpClientConnection conn = getConnection(); - if (conn != null) { - return conn.isStale(); - } else { - return true; - } + return conn != null ? conn.isStale() : true; } @Override @@ -203,11 +195,7 @@ public int getRemotePort() { @Override public Object getAttribute(final String id) { final ManagedHttpClientConnection conn = getValidConnection(); - if (conn instanceof HttpContext) { - return ((HttpContext) conn).getAttribute(id); - } else { - return null; - } + return conn instanceof HttpContext ? ((HttpContext) conn).getAttribute(id) : null; } @Override @@ -221,11 +209,7 @@ public void setAttribute(final String id, final Object obj) { @Override public Object removeAttribute(final String id) { final ManagedHttpClientConnection conn = getValidConnection(); - if (conn instanceof HttpContext) { - return ((HttpContext) conn).removeAttribute(id); - } else { - return null; - } + return conn instanceof HttpContext ? ((HttpContext) conn).removeAttribute(id) : null; } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java index 76af8e81b8..b84737a895 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java @@ -153,11 +153,9 @@ public void connect( } catch (final ConnectException ex) { if (last) { final String msg = ex.getMessage(); - if ("Connection timed out".equals(msg)) { - throw new ConnectTimeoutException(ex, host, addresses); - } else { - throw new HttpHostConnectException(ex, host, addresses); - } + throw "Connection timed out".equals(msg) + ? new ConnectTimeoutException(ex, host, addresses) + : new HttpHostConnectException(ex, host, addresses); } } catch (final NoRouteToHostException ex) { if (last) { diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java index 1a74f5ea95..73e827c956 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultManagedHttpClientConnection.java @@ -62,16 +62,16 @@ public class DefaultManagedHttpClientConnection extends DefaultBHttpClientConnec public DefaultManagedHttpClientConnection( final String id, - final int buffersize, + final int bufferSize, final int fragmentSizeHint, - final CharsetDecoder chardecoder, - final CharsetEncoder charencoder, + final CharsetDecoder charDecoder, + final CharsetEncoder charEncoder, final MessageConstraints constraints, final ContentLengthStrategy incomingContentStrategy, final ContentLengthStrategy outgoingContentStrategy, final HttpMessageWriterFactory requestWriterFactory, final HttpMessageParserFactory responseParserFactory) { - super(buffersize, fragmentSizeHint, chardecoder, charencoder, + super(bufferSize, fragmentSizeHint, charDecoder, charEncoder, constraints, incomingContentStrategy, outgoingContentStrategy, requestWriterFactory, responseParserFactory); this.id = id; @@ -80,8 +80,8 @@ public DefaultManagedHttpClientConnection( public DefaultManagedHttpClientConnection( final String id, - final int buffersize) { - this(id, buffersize, buffersize, null, null, null, null, null, null, null); + final int bufferSize) { + this(id, bufferSize, bufferSize, null, null, null, null, null, null, null); } @Override @@ -128,11 +128,7 @@ public Socket getSocket() { @Override public SSLSession getSSLSession() { final Socket socket = super.getSocket(); - if (socket instanceof SSLSocket) { - return ((SSLSocket) socket).getSession(); - } else { - return null; - } + return socket instanceof SSLSocket ? ((SSLSocket) socket).getSession() : null; } } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java index 3652115c1d..6bc81742c6 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultRoutePlanner.java @@ -92,11 +92,9 @@ public HttpRoute determineRoute( target = host; } final boolean secure = target.getSchemeName().equalsIgnoreCase("https"); - if (proxy == null) { - return new HttpRoute(target, local, secure); - } else { - return new HttpRoute(target, local, proxy, secure); - } + return proxy == null + ? new HttpRoute(target, local, secure) + : new HttpRoute(target, local, proxy, secure); } /** diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java index 6d3b34fe6a..24a7ad8584 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/LoggingManagedHttpClientConnection.java @@ -46,29 +46,29 @@ class LoggingManagedHttpClientConnection extends DefaultManagedHttpClientConnection { private final Log log; - private final Log headerlog; + private final Log headerLog; private final Wire wire; public LoggingManagedHttpClientConnection( final String id, final Log log, - final Log headerlog, - final Log wirelog, - final int buffersize, + final Log headerLog, + final Log wireLog, + final int bufferSize, final int fragmentSizeHint, - final CharsetDecoder chardecoder, - final CharsetEncoder charencoder, + final CharsetDecoder charDecoder, + final CharsetEncoder charEncoder, final MessageConstraints constraints, final ContentLengthStrategy incomingContentStrategy, final ContentLengthStrategy outgoingContentStrategy, final HttpMessageWriterFactory requestWriterFactory, final HttpMessageParserFactory responseParserFactory) { - super(id, buffersize, fragmentSizeHint, chardecoder, charencoder, + super(id, bufferSize, fragmentSizeHint, charDecoder, charEncoder, constraints, incomingContentStrategy, outgoingContentStrategy, requestWriterFactory, responseParserFactory); this.log = log; - this.headerlog = headerlog; - this.wire = new Wire(wirelog, id); + this.headerLog = headerLog; + this.wire = new Wire(wireLog, id); } @Override @@ -118,22 +118,22 @@ protected OutputStream getSocketOutputStream(final Socket socket) throws IOExcep @Override protected void onResponseReceived(final HttpResponse response) { - if (response != null && this.headerlog.isDebugEnabled()) { - this.headerlog.debug(getId() + " << " + response.getStatusLine().toString()); + if (response != null && this.headerLog.isDebugEnabled()) { + this.headerLog.debug(getId() + " << " + response.getStatusLine().toString()); final Header[] headers = response.getAllHeaders(); for (final Header header : headers) { - this.headerlog.debug(getId() + " << " + header.toString()); + this.headerLog.debug(getId() + " << " + header.toString()); } } } @Override protected void onRequestSubmitted(final HttpRequest request) { - if (request != null && this.headerlog.isDebugEnabled()) { - this.headerlog.debug(getId() + " >> " + request.getRequestLine().toString()); + if (request != null && this.headerLog.isDebugEnabled()) { + this.headerLog.debug(getId() + " >> " + request.getRequestLine().toString()); final Header[] headers = request.getAllHeaders(); for (final Header header : headers) { - this.headerlog.debug(getId() + " >> " + header.toString()); + this.headerLog.debug(getId() + " >> " + header.toString()); } } } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java b/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java index 7057c3e3fe..ff4029525b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/ManagedHttpClientConnectionFactory.java @@ -63,8 +63,8 @@ public class ManagedHttpClientConnectionFactory public static final ManagedHttpClientConnectionFactory INSTANCE = new ManagedHttpClientConnectionFactory(); private final Log log = LogFactory.getLog(DefaultManagedHttpClientConnection.class); - private final Log headerlog = LogFactory.getLog("org.apache.http.headers"); - private final Log wirelog = LogFactory.getLog("org.apache.http.wire"); + private final Log headerLog = LogFactory.getLog("org.apache.http.headers"); + private final Log wireLog = LogFactory.getLog("org.apache.http.wire"); private final HttpMessageWriterFactory requestWriterFactory; private final HttpMessageParserFactory responseParserFactory; @@ -108,31 +108,31 @@ public ManagedHttpClientConnectionFactory() { @Override public ManagedHttpClientConnection create(final HttpRoute route, final ConnectionConfig config) { final ConnectionConfig cconfig = config != null ? config : ConnectionConfig.DEFAULT; - CharsetDecoder chardecoder = null; - CharsetEncoder charencoder = null; + CharsetDecoder charDecoder = null; + CharsetEncoder charEncoder = null; final Charset charset = cconfig.getCharset(); final CodingErrorAction malformedInputAction = cconfig.getMalformedInputAction() != null ? cconfig.getMalformedInputAction() : CodingErrorAction.REPORT; final CodingErrorAction unmappableInputAction = cconfig.getUnmappableInputAction() != null ? cconfig.getUnmappableInputAction() : CodingErrorAction.REPORT; if (charset != null) { - chardecoder = charset.newDecoder(); - chardecoder.onMalformedInput(malformedInputAction); - chardecoder.onUnmappableCharacter(unmappableInputAction); - charencoder = charset.newEncoder(); - charencoder.onMalformedInput(malformedInputAction); - charencoder.onUnmappableCharacter(unmappableInputAction); + charDecoder = charset.newDecoder(); + charDecoder.onMalformedInput(malformedInputAction); + charDecoder.onUnmappableCharacter(unmappableInputAction); + charEncoder = charset.newEncoder(); + charEncoder.onMalformedInput(malformedInputAction); + charEncoder.onUnmappableCharacter(unmappableInputAction); } final String id = "http-outgoing-" + Long.toString(COUNTER.getAndIncrement()); return new LoggingManagedHttpClientConnection( id, log, - headerlog, - wirelog, + headerLog, + wireLog, cconfig.getBufferSize(), cconfig.getFragmentSizeHint(), - chardecoder, - charencoder, + charDecoder, + charEncoder, cconfig.getMessageConstraints(), incomingContentStrategy, outgoingContentStrategy, diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java index b20e0248e4..4c38bd88c4 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java @@ -121,8 +121,8 @@ public PoolingHttpClientConnectionManager() { this(getDefaultRegistry()); } - public PoolingHttpClientConnectionManager(final long timeToLive, final TimeUnit tunit) { - this(getDefaultRegistry(), null, null ,null, timeToLive, tunit); + public PoolingHttpClientConnectionManager(final long timeToLive, final TimeUnit timeUnit) { + this(getDefaultRegistry(), null, null ,null, timeToLive, timeUnit); } public PoolingHttpClientConnectionManager( @@ -159,11 +159,11 @@ public PoolingHttpClientConnectionManager( final HttpConnectionFactory connFactory, final SchemePortResolver schemePortResolver, final DnsResolver dnsResolver, - final long timeToLive, final TimeUnit tunit) { + final long timeToLive, final TimeUnit timeUnit) { this( new DefaultHttpClientConnectionOperator(socketFactoryRegistry, schemePortResolver, dnsResolver), connFactory, - timeToLive, tunit + timeToLive, timeUnit ); } @@ -173,11 +173,11 @@ public PoolingHttpClientConnectionManager( public PoolingHttpClientConnectionManager( final HttpClientConnectionOperator httpClientConnectionOperator, final HttpConnectionFactory connFactory, - final long timeToLive, final TimeUnit tunit) { + final long timeToLive, final TimeUnit timeUnit) { super(); this.configData = new ConfigData(); this.pool = new CPool(new InternalConnectionFactory( - this.configData, connFactory), 2, 20, timeToLive, tunit); + this.configData, connFactory), 2, 20, timeToLive, timeUnit); this.pool.setValidateAfterInactivity(2000); this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator"); this.isShutDown = new AtomicBoolean(false); @@ -275,8 +275,8 @@ public boolean cancel() { @Override public HttpClientConnection get( final long timeout, - final TimeUnit tunit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException { - final HttpClientConnection conn = leaseConnection(future, timeout, tunit); + final TimeUnit timeUnit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException { + final HttpClientConnection conn = leaseConnection(future, timeout, timeUnit); if (conn.isOpen()) { final HttpHost host; if (route.getProxyHost() != null) { @@ -297,10 +297,10 @@ public HttpClientConnection get( protected HttpClientConnection leaseConnection( final Future future, final long timeout, - final TimeUnit tunit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException { + final TimeUnit timeUnit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException { final CPoolEntry entry; try { - entry = future.get(timeout, tunit); + entry = future.get(timeout, timeUnit); if (entry == null || future.isCancelled()) { throw new InterruptedException(); } @@ -318,7 +318,7 @@ protected HttpClientConnection leaseConnection( public void releaseConnection( final HttpClientConnection managedConn, final Object state, - final long keepalive, final TimeUnit tunit) { + final long keepalive, final TimeUnit timeUnit) { Args.notNull(managedConn, "Managed connection"); synchronized (managedConn) { final CPoolEntry entry = CPoolProxy.detach(managedConn); @@ -328,7 +328,7 @@ public void releaseConnection( final ManagedHttpClientConnection conn = entry.getConnection(); try { if (conn.isOpen()) { - final TimeUnit effectiveUnit = tunit != null ? tunit : TimeUnit.MILLISECONDS; + final TimeUnit effectiveUnit = timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS; entry.setState(state); entry.updateExpiry(keepalive, effectiveUnit); if (this.log.isDebugEnabled()) { @@ -416,11 +416,11 @@ public void shutdown() { } @Override - public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { + public void closeIdleConnections(final long idleTimeout, final TimeUnit timeUnit) { if (this.log.isDebugEnabled()) { - this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); + this.log.debug("Closing connections idle longer than " + idleTimeout + " " + timeUnit); } - this.pool.closeIdle(idleTimeout, tunit); + this.pool.closeIdle(idleTimeout, timeUnit); } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java b/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java index 48195e5f0c..07b2e778af 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/Wire.java @@ -59,11 +59,11 @@ public Wire(final Log log) { this(log, ""); } - private void wire(final String header, final InputStream instream) + private void wire(final String header, final InputStream inStream) throws IOException { final StringBuilder buffer = new StringBuilder(); int ch; - while ((ch = instream.read()) != -1) { + while ((ch = inStream.read()) != -1) { if (ch == 13) { buffer.append("[\\r]"); } else if (ch == 10) { @@ -93,16 +93,16 @@ public boolean enabled() { return log.isDebugEnabled(); } - public void output(final InputStream outstream) + public void output(final InputStream outStream) throws IOException { - Args.notNull(outstream, "Output"); - wire(">> ", outstream); + Args.notNull(outStream, "Output"); + wire(">> ", outStream); } - public void input(final InputStream instream) + public void input(final InputStream inStream) throws IOException { - Args.notNull(instream, "Input"); - wire("<< ", instream); + Args.notNull(inStream, "Input"); + wire("<< ", inStream); } public void output(final byte[] b, final int off, final int len) diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java index c291f1c41c..72770a61a5 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/DefaultCookieSpec.java @@ -105,14 +105,14 @@ public List parse( final CookieOrigin origin) throws MalformedCookieException { Args.notNull(header, "Header"); Args.notNull(origin, "Cookie origin"); - HeaderElement[] helems = header.getElements(); + HeaderElement[] hElems = header.getElements(); boolean versioned = false; boolean netscape = false; - for (final HeaderElement helem: helems) { - if (helem.getParameterByName("version") != null) { + for (final HeaderElement hElem: hElems) { + if (hElem.getParameterByName("version") != null) { versioned = true; } - if (helem.getParameterByName("expires") != null) { + if (hElem.getParameterByName("expires") != null) { netscape = true; } } @@ -128,23 +128,20 @@ public List parse( ((FormattedHeader) header).getValuePos(), buffer.length()); } else { - final String s = header.getValue(); - if (s == null) { + final String hValue = header.getValue(); + if (hValue == null) { throw new MalformedCookieException("Header value is null"); } - buffer = new CharArrayBuffer(s.length()); - buffer.append(s); + buffer = new CharArrayBuffer(hValue.length()); + buffer.append(hValue); cursor = new ParserCursor(0, buffer.length()); } - helems = new HeaderElement[] { parser.parseHeader(buffer, cursor) }; - return netscapeDraft.parse(helems, origin); - } else { - if (SM.SET_COOKIE2.equals(header.getName())) { - return strict.parse(helems, origin); - } else { - return obsoleteStrict.parse(helems, origin); - } + hElems = new HeaderElement[] { parser.parseHeader(buffer, cursor) }; + return netscapeDraft.parse(hElems, origin); } + return SM.SET_COOKIE2.equals(header.getName()) + ? strict.parse(hElems, origin) + : obsoleteStrict.parse(hElems, origin); } @Override @@ -169,14 +166,11 @@ public boolean match(final Cookie cookie, final CookieOrigin origin) { Args.notNull(cookie, "Cookie"); Args.notNull(origin, "Cookie origin"); if (cookie.getVersion() > 0) { - if (cookie instanceof SetCookie2) { - return strict.match(cookie, origin); - } else { - return obsoleteStrict.match(cookie, origin); - } - } else { - return netscapeDraft.match(cookie, origin); + return cookie instanceof SetCookie2 + ? strict.match(cookie, origin) + : obsoleteStrict.match(cookie, origin); } + return netscapeDraft.match(cookie, origin); } @Override @@ -193,14 +187,11 @@ public List
          formatCookies(final List cookies) { } } if (version > 0) { - if (isSetCookie2) { - return strict.formatCookies(cookies); - } else { - return obsoleteStrict.formatCookies(cookies); - } - } else { - return netscapeDraft.formatCookies(cookies); + return isSetCookie2 + ? strict.formatCookies(cookies) + : obsoleteStrict.formatCookies(cookies); } + return netscapeDraft.formatCookies(cookies); } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java index 8043bb48af..02fdbdc7c6 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/LaxExpiresHandler.java @@ -205,10 +205,9 @@ private void copyContent(final CharSequence buf, final ParserCursor cursor, fina final char current = buf.charAt(i); if (DELIMS.get(current)) { break; - } else { - pos++; - dst.append(current); } + pos++; + dst.append(current); } cursor.updatePos(pos); } diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java index dbc205e0a3..429782e965 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java @@ -143,11 +143,7 @@ public List
          formatCookies(final List cookies) { } else { cookieList = cookies; } - if (this.oneHeader) { - return doFormatOneHeader(cookieList); - } else { - return doFormatManyHeaders(cookieList); - } + return this.oneHeader ? doFormatOneHeader(cookieList) : doFormatManyHeaders(cookieList); } private List
          doFormatOneHeader(final List cookies) { diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java index 5fca006ad0..5b7716405b 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/RFC2965Spec.java @@ -64,7 +64,6 @@ public class RFC2965Spec extends RFC2109Spec { /** * Default constructor - * */ public RFC2965Spec() { this(null, false); @@ -222,7 +221,7 @@ protected void formatCookieAsVer(final CharArrayBuffer buffer, * @param origin origin where cookie is received from or being sent to. */ private static CookieOrigin adjustEffectiveHost(final CookieOrigin origin) { - String host = origin.getHost(); + final String host = origin.getHost(); // Test if the host name appears to be a fully qualified DNS name, // IPv4 address or IPv6 address @@ -234,16 +233,13 @@ private static CookieOrigin adjustEffectiveHost(final CookieOrigin origin) { break; } } - if (isLocalHost) { - host += ".local"; - return new CookieOrigin( - host, - origin.getPort(), - origin.getPath(), - origin.isSecure()); - } else { - return origin; - } + return isLocalHost + ? new CookieOrigin( + host + ".local", + origin.getPort(), + origin.getPath(), + origin.isSecure()) + : origin; } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java index daa5a319fc..c102f91275 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java @@ -56,7 +56,7 @@ class ConnectionHolder implements ConnectionReleaseTrigger, Cancellable, Closeab private volatile boolean reusable; private volatile Object state; private volatile long validDuration; - private volatile TimeUnit tunit; + private volatile TimeUnit timeUnit; public ConnectionHolder( final Log log, @@ -85,10 +85,10 @@ public void setState(final Object state) { this.state = state; } - public void setValidFor(final long duration, final TimeUnit tunit) { + public void setValidFor(final long duration, final TimeUnit timeUnit) { synchronized (this.managedConn) { this.validDuration = duration; - this.tunit = tunit; + this.timeUnit = timeUnit; } } @@ -97,7 +97,7 @@ private void releaseConnection(final boolean reusable) { synchronized (this.managedConn) { if (reusable) { this.manager.releaseConnection(this.managedConn, - this.state, this.validDuration, this.tunit); + this.state, this.validDuration, this.timeUnit); } else { try { this.managedConn.close(); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java index 1affd94a97..e5bba360cf 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java @@ -116,9 +116,9 @@ public InputStream getContent() throws IOException, IllegalStateException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { + public void writeTo(final OutputStream outStream) throws IOException { consumed = true; - original.writeTo(outstream); + original.writeTo(outStream); } @Override diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java index 6f53c23140..47c5ac9ed5 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java @@ -94,10 +94,10 @@ public void consumeContent() throws IOException { } @Override - public void writeTo(final OutputStream outstream) throws IOException { + public void writeTo(final OutputStream outStream) throws IOException { try { - if (outstream != null) { - this.wrappedEntity.writeTo(outstream); + if (outStream != null) { + this.wrappedEntity.writeTo(outStream); } releaseConnection(); } catch (final IOException ex) { diff --git a/httpclient/src/test/java/org/apache/http/auth/TestCredentials.java b/httpclient/src/test/java/org/apache/http/auth/TestCredentials.java index 10564a044f..937acc4d85 100644 --- a/httpclient/src/test/java/org/apache/http/auth/TestCredentials.java +++ b/httpclient/src/test/java/org/apache/http/auth/TestCredentials.java @@ -203,13 +203,13 @@ public void testNTCredentialsEquals() { public void testUsernamePasswordCredentialsSerialization() throws Exception { final UsernamePasswordCredentials orig = new UsernamePasswordCredentials("name", "pwd"); final ByteArrayOutputStream outbuffer = new ByteArrayOutputStream(); - final ObjectOutputStream outstream = new ObjectOutputStream(outbuffer); - outstream.writeObject(orig); - outstream.close(); + final ObjectOutputStream outStream = new ObjectOutputStream(outbuffer); + outStream.writeObject(orig); + outStream.close(); final byte[] raw = outbuffer.toByteArray(); - final ByteArrayInputStream inbuffer = new ByteArrayInputStream(raw); - final ObjectInputStream instream = new ObjectInputStream(inbuffer); - final UsernamePasswordCredentials clone = (UsernamePasswordCredentials) instream.readObject(); + final ByteArrayInputStream inBuffer = new ByteArrayInputStream(raw); + final ObjectInputStream inStream = new ObjectInputStream(inBuffer); + final UsernamePasswordCredentials clone = (UsernamePasswordCredentials) inStream.readObject(); Assert.assertEquals(orig, clone); } @@ -217,13 +217,13 @@ public void testUsernamePasswordCredentialsSerialization() throws Exception { public void testNTCredentialsSerialization() throws Exception { final NTCredentials orig = new NTCredentials("name", "pwd", "somehost", "domain"); final ByteArrayOutputStream outbuffer = new ByteArrayOutputStream(); - final ObjectOutputStream outstream = new ObjectOutputStream(outbuffer); - outstream.writeObject(orig); - outstream.close(); + final ObjectOutputStream outStream = new ObjectOutputStream(outbuffer); + outStream.writeObject(orig); + outStream.close(); final byte[] raw = outbuffer.toByteArray(); - final ByteArrayInputStream inbuffer = new ByteArrayInputStream(raw); - final ObjectInputStream instream = new ObjectInputStream(inbuffer); - final NTCredentials clone = (NTCredentials) instream.readObject(); + final ByteArrayInputStream inBuffer = new ByteArrayInputStream(raw); + final ObjectInputStream inStream = new ObjectInputStream(inBuffer); + final NTCredentials clone = (NTCredentials) inStream.readObject(); Assert.assertEquals(orig, clone); } diff --git a/httpclient/src/test/java/org/apache/http/client/entity/TestDecompressingEntity.java b/httpclient/src/test/java/org/apache/http/client/entity/TestDecompressingEntity.java index 347d99d74d..b36a609af3 100644 --- a/httpclient/src/test/java/org/apache/http/client/entity/TestDecompressingEntity.java +++ b/httpclient/src/test/java/org/apache/http/client/entity/TestDecompressingEntity.java @@ -97,8 +97,8 @@ public ChecksumEntity(final HttpEntity wrapped, final Checksum checksum) { super(wrapped, new InputStreamFactory() { @Override - public InputStream create(final InputStream instream) throws IOException { - return new CheckedInputStream(instream, checksum); + public InputStream create(final InputStream inStream) throws IOException { + return new CheckedInputStream(inStream, checksum); } }); diff --git a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java index 2f9ba9a685..516299dcbc 100644 --- a/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java +++ b/httpclient/src/test/java/org/apache/http/client/entity/TestGZip.java @@ -41,6 +41,7 @@ import org.apache.http.util.EntityUtils; import org.junit.Assert; import org.junit.Test; +import org.mockito.Matchers; import org.mockito.Mockito; public class TestGZip { @@ -71,7 +72,7 @@ public void testCompressionDecompression() throws Exception { @Test public void testCompressionIOExceptionLeavesOutputStreamOpen() throws Exception { final HttpEntity in = Mockito.mock(HttpEntity.class); - Mockito.doThrow(new IOException("Ooopsie")).when(in).writeTo(Mockito.any()); + Mockito.doThrow(new IOException("Ooopsie")).when(in).writeTo(Matchers.any()); final GzipCompressingEntity gzipe = new GzipCompressingEntity(in); final OutputStream out = Mockito.mock(OutputStream.class); try { diff --git a/httpclient/src/test/java/org/apache/http/client/methods/TestHttpRequestBase.java b/httpclient/src/test/java/org/apache/http/client/methods/TestHttpRequestBase.java index 51a794e094..21653875b0 100644 --- a/httpclient/src/test/java/org/apache/http/client/methods/TestHttpRequestBase.java +++ b/httpclient/src/test/java/org/apache/http/client/methods/TestHttpRequestBase.java @@ -97,8 +97,8 @@ public void testCloneEntityEnclosingRequests() throws Exception { @Test(expected=CloneNotSupportedException.class) public void testCloneStreamingEntityEnclosingRequests() throws Exception { - final ByteArrayInputStream instream = new ByteArrayInputStream(new byte[] {}); - final InputStreamEntity e2 = new InputStreamEntity(instream, -1); + final ByteArrayInputStream inStream = new ByteArrayInputStream(new byte[] {}); + final InputStreamEntity e2 = new InputStreamEntity(inStream, -1); final HttpPost httppost = new HttpPost("http://host/path"); httppost.setEntity(e2); httppost.clone(); diff --git a/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAddCookies.java b/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAddCookies.java index 1c8cf42a9a..4854f52421 100644 --- a/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAddCookies.java +++ b/httpclient/src/test/java/org/apache/http/client/protocol/TestRequestAddCookies.java @@ -57,6 +57,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.mockito.Matchers; import org.mockito.Mockito; public class TestRequestAddCookies { @@ -402,7 +403,7 @@ public void testExcludeExpiredCookies() throws Exception { Assert.assertNotNull(headers2); Assert.assertEquals(0, headers2.length); - Mockito.verify(this.cookieStore, Mockito.times(1)).clearExpired(Mockito.any()); + Mockito.verify(this.cookieStore, Mockito.times(1)).clearExpired(Matchers.any()); } @Test diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestHttpClientUtils.java b/httpclient/src/test/java/org/apache/http/client/utils/TestHttpClientUtils.java index b1fa88d729..f8d778fb9d 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestHttpClientUtils.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestHttpClientUtils.java @@ -66,22 +66,22 @@ public void testCloseQuietlyResponseEntityNonStreaming() throws Exception { public void testCloseQuietlyResponseEntity() throws Exception { final HttpResponse response = Mockito.mock(HttpResponse.class); final HttpEntity entity = Mockito.mock(HttpEntity.class); - final InputStream instream = Mockito.mock(InputStream.class); + final InputStream inStream = Mockito.mock(InputStream.class); Mockito.when(response.getEntity()).thenReturn(entity); Mockito.when(entity.isStreaming()).thenReturn(Boolean.TRUE); - Mockito.when(entity.getContent()).thenReturn(instream); + Mockito.when(entity.getContent()).thenReturn(inStream); HttpClientUtils.closeQuietly(response); - Mockito.verify(instream).close(); + Mockito.verify(inStream).close(); } @Test public void testCloseQuietlyResponseIgnoreIOError() throws Exception { final HttpResponse response = Mockito.mock(HttpResponse.class); final HttpEntity entity = Mockito.mock(HttpEntity.class); - final InputStream instream = Mockito.mock(InputStream.class); + final InputStream inStream = Mockito.mock(InputStream.class); Mockito.when(response.getEntity()).thenReturn(entity); - Mockito.when(entity.getContent()).thenReturn(instream); - Mockito.doThrow(new IOException()).when(instream).close(); + Mockito.when(entity.getContent()).thenReturn(inStream); + Mockito.doThrow(new IOException()).when(inStream).close(); HttpClientUtils.closeQuietly(response); } @@ -114,12 +114,12 @@ public void testCloseQuietlyCloseableResponseEntityNonStreaming() throws Excepti public void testCloseQuietlyCloseableResponseEntity() throws Exception { final CloseableHttpResponse response = Mockito.mock(CloseableHttpResponse.class); final HttpEntity entity = Mockito.mock(HttpEntity.class); - final InputStream instream = Mockito.mock(InputStream.class); + final InputStream inStream = Mockito.mock(InputStream.class); Mockito.when(response.getEntity()).thenReturn(entity); Mockito.when(entity.isStreaming()).thenReturn(Boolean.TRUE); - Mockito.when(entity.getContent()).thenReturn(instream); + Mockito.when(entity.getContent()).thenReturn(inStream); HttpClientUtils.closeQuietly(response); - Mockito.verify(instream).close(); + Mockito.verify(inStream).close(); Mockito.verify(response).close(); } @@ -127,10 +127,10 @@ public void testCloseQuietlyCloseableResponseEntity() throws Exception { public void testCloseQuietlyCloseableResponseIgnoreIOError() throws Exception { final CloseableHttpResponse response = Mockito.mock(CloseableHttpResponse.class); final HttpEntity entity = Mockito.mock(HttpEntity.class); - final InputStream instream = Mockito.mock(InputStream.class); + final InputStream inStream = Mockito.mock(InputStream.class); Mockito.when(response.getEntity()).thenReturn(entity); - Mockito.when(entity.getContent()).thenReturn(instream); - Mockito.doThrow(new IOException()).when(instream).close(); + Mockito.when(entity.getContent()).thenReturn(inStream); + Mockito.doThrow(new IOException()).when(inStream).close(); HttpClientUtils.closeQuietly(response); } diff --git a/httpclient/src/test/java/org/apache/http/conn/TestEofSensorInputStream.java b/httpclient/src/test/java/org/apache/http/conn/TestEofSensorInputStream.java index 396f4314fe..7770e7744a 100644 --- a/httpclient/src/test/java/org/apache/http/conn/TestEofSensorInputStream.java +++ b/httpclient/src/test/java/org/apache/http/conn/TestEofSensorInputStream.java @@ -37,15 +37,15 @@ @SuppressWarnings({"boxing","static-access"}) // test code public class TestEofSensorInputStream { - private InputStream instream; + private InputStream inStream; private EofSensorWatcher eofwatcher; private EofSensorInputStream eofstream; @Before public void setup() throws Exception { - instream = Mockito.mock(InputStream.class); + inStream = Mockito.mock(InputStream.class); eofwatcher = Mockito.mock(EofSensorWatcher.class); - eofstream = new EofSensorInputStream(instream, eofwatcher); + eofstream = new EofSensorInputStream(inStream, eofwatcher); } @Test @@ -57,8 +57,8 @@ public void testClose() throws Exception { Assert.assertTrue(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(instream, Mockito.times(1)).close(); - Mockito.verify(eofwatcher).streamClosed(instream); + Mockito.verify(inStream, Mockito.times(1)).close(); + Mockito.verify(eofwatcher).streamClosed(inStream); eofstream.close(); } @@ -75,7 +75,7 @@ public void testCloseIOError() throws Exception { Assert.assertTrue(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(eofwatcher).streamClosed(instream); + Mockito.verify(eofwatcher).streamClosed(inStream); } @Test @@ -87,8 +87,8 @@ public void testReleaseConnection() throws Exception { Assert.assertTrue(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(instream, Mockito.times(1)).close(); - Mockito.verify(eofwatcher).streamClosed(instream); + Mockito.verify(inStream, Mockito.times(1)).close(); + Mockito.verify(eofwatcher).streamClosed(inStream); eofstream.releaseConnection(); } @@ -102,8 +102,8 @@ public void testAbortConnection() throws Exception { Assert.assertTrue(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(instream, Mockito.times(1)).close(); - Mockito.verify(eofwatcher).streamAbort(instream); + Mockito.verify(inStream, Mockito.times(1)).close(); + Mockito.verify(eofwatcher).streamAbort(inStream); eofstream.abortConnection(); } @@ -120,28 +120,28 @@ public void testAbortConnectionIOError() throws Exception { Assert.assertTrue(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(eofwatcher).streamAbort(instream); + Mockito.verify(eofwatcher).streamAbort(inStream); } @Test public void testRead() throws Exception { Mockito.when(eofwatcher.eofDetected(Mockito.any())).thenReturn(Boolean.TRUE); - Mockito.when(instream.read()).thenReturn(0, -1); + Mockito.when(inStream.read()).thenReturn(0, -1); Assert.assertEquals(0, eofstream.read()); Assert.assertFalse(eofstream.isSelfClosed()); Assert.assertNotNull(eofstream.getWrappedStream()); - Mockito.verify(eofwatcher, Mockito.never()).eofDetected(instream); + Mockito.verify(eofwatcher, Mockito.never()).eofDetected(inStream); Assert.assertEquals(-1, eofstream.read()); Assert.assertFalse(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(instream, Mockito.times(1)).close(); - Mockito.verify(eofwatcher).eofDetected(instream); + Mockito.verify(inStream, Mockito.times(1)).close(); + Mockito.verify(eofwatcher).eofDetected(inStream); Assert.assertEquals(-1, eofstream.read()); } @@ -149,7 +149,7 @@ public void testRead() throws Exception { @Test public void testReadIOError() throws Exception { Mockito.when(eofwatcher.eofDetected(Mockito.any())).thenReturn(Boolean.TRUE); - Mockito.when(instream.read()).thenThrow(new IOException()); + Mockito.when(inStream.read()).thenThrow(new IOException()); try { eofstream.read(); @@ -159,13 +159,13 @@ public void testReadIOError() throws Exception { Assert.assertFalse(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(eofwatcher).streamAbort(instream); + Mockito.verify(eofwatcher).streamAbort(inStream); } @Test public void testReadByteArray() throws Exception { Mockito.when(eofwatcher.eofDetected(Mockito.any())).thenReturn(Boolean.TRUE); - Mockito.when(instream.read(Mockito.any(), Mockito.anyInt(), Mockito.anyInt())) + Mockito.when(inStream.read(Mockito.any(), Mockito.anyInt(), Mockito.anyInt())) .thenReturn(1, -1); final byte[] tmp = new byte[1]; @@ -175,15 +175,15 @@ public void testReadByteArray() throws Exception { Assert.assertFalse(eofstream.isSelfClosed()); Assert.assertNotNull(eofstream.getWrappedStream()); - Mockito.verify(eofwatcher, Mockito.never()).eofDetected(instream); + Mockito.verify(eofwatcher, Mockito.never()).eofDetected(inStream); Assert.assertEquals(-1, eofstream.read(tmp)); Assert.assertFalse(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(instream, Mockito.times(1)).close(); - Mockito.verify(eofwatcher).eofDetected(instream); + Mockito.verify(inStream, Mockito.times(1)).close(); + Mockito.verify(eofwatcher).eofDetected(inStream); Assert.assertEquals(-1, eofstream.read(tmp)); } @@ -191,7 +191,7 @@ public void testReadByteArray() throws Exception { @Test public void testReadByteArrayIOError() throws Exception { Mockito.when(eofwatcher.eofDetected(Mockito.any())).thenReturn(Boolean.TRUE); - Mockito.when(instream.read(Mockito.any(), Mockito.anyInt(), Mockito.anyInt())) + Mockito.when(inStream.read(Mockito.any(), Mockito.anyInt(), Mockito.anyInt())) .thenThrow(new IOException()); final byte[] tmp = new byte[1]; @@ -203,7 +203,7 @@ public void testReadByteArrayIOError() throws Exception { Assert.assertFalse(eofstream.isSelfClosed()); Assert.assertNull(eofstream.getWrappedStream()); - Mockito.verify(eofwatcher).streamAbort(instream); + Mockito.verify(eofwatcher).streamAbort(inStream); } @Test diff --git a/httpclient/src/test/java/org/apache/http/impl/client/MockConnPoolControl.java b/httpclient/src/test/java/org/apache/http/impl/client/MockConnPoolControl.java index d8a4c3d8d6..299e191aa7 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/MockConnPoolControl.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/MockConnPoolControl.java @@ -85,11 +85,7 @@ public void setMaxPerRoute(final HttpRoute route, final int max) { @Override public int getMaxPerRoute(final HttpRoute route) { final Integer max = this.maxPerHostMap.get(route); - if (max != null) { - return max.intValue(); - } else { - return this.defaultMax; - } + return max != null ? max.intValue() : this.defaultMax; } public void setMaxForRoutes(final Map map) { diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestAbstractResponseHandler.java b/httpclient/src/test/java/org/apache/http/impl/client/TestAbstractResponseHandler.java index 6a2930c5ca..cfc2bd6539 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/TestAbstractResponseHandler.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/TestAbstractResponseHandler.java @@ -69,10 +69,10 @@ public Integer handleEntity(final HttpEntity entity) throws IOException { @SuppressWarnings("boxing") @Test public void testUnsuccessfulResponse() throws Exception { - final InputStream instream = Mockito.mock(InputStream.class); + final InputStream inStream = Mockito.mock(InputStream.class); final HttpEntity entity = Mockito.mock(HttpEntity.class); Mockito.when(entity.isStreaming()).thenReturn(true); - Mockito.when(entity.getContent()).thenReturn(instream); + Mockito.when(entity.getContent()).thenReturn(inStream); final StatusLine sl = new BasicStatusLine(HttpVersion.HTTP_1_1, 404, "Not Found"); final HttpResponse response = Mockito.mock(HttpResponse.class); Mockito.when(response.getStatusLine()).thenReturn(sl); @@ -87,7 +87,7 @@ public void testUnsuccessfulResponse() throws Exception { Assert.assertEquals("Not Found", ex.getMessage()); } Mockito.verify(entity).getContent(); - Mockito.verify(instream).close(); + Mockito.verify(inStream).close(); } } diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestBasicCookieStore.java b/httpclient/src/test/java/org/apache/http/impl/client/TestBasicCookieStore.java index a329758947..67603456d0 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/TestBasicCookieStore.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/TestBasicCookieStore.java @@ -49,15 +49,15 @@ public void testBasics() throws Exception { final BasicCookieStore store = new BasicCookieStore(); store.addCookie(new BasicClientCookie("name1", "value1")); store.addCookies(new BasicClientCookie[] {new BasicClientCookie("name2", "value2")}); - List l = store.getCookies(); - Assert.assertNotNull(l); - Assert.assertEquals(2, l.size()); - Assert.assertEquals("name1", l.get(0).getName()); - Assert.assertEquals("name2", l.get(1).getName()); + List list = store.getCookies(); + Assert.assertNotNull(list); + Assert.assertEquals(2, list.size()); + Assert.assertEquals("name1", list.get(0).getName()); + Assert.assertEquals("name2", list.get(1).getName()); store.clear(); - l = store.getCookies(); - Assert.assertNotNull(l); - Assert.assertEquals(0, l.size()); + list = store.getCookies(); + Assert.assertNotNull(list); + Assert.assertEquals(0, list.size()); } @Test @@ -80,13 +80,13 @@ public void testSerialization() throws Exception { orig.addCookie(new BasicClientCookie("name1", "value1")); orig.addCookie(new BasicClientCookie("name2", "value2")); final ByteArrayOutputStream outbuffer = new ByteArrayOutputStream(); - final ObjectOutputStream outstream = new ObjectOutputStream(outbuffer); - outstream.writeObject(orig); - outstream.close(); + final ObjectOutputStream outStream = new ObjectOutputStream(outbuffer); + outStream.writeObject(orig); + outStream.close(); final byte[] raw = outbuffer.toByteArray(); - final ByteArrayInputStream inbuffer = new ByteArrayInputStream(raw); - final ObjectInputStream instream = new ObjectInputStream(inbuffer); - final BasicCookieStore clone = (BasicCookieStore) instream.readObject(); + final ByteArrayInputStream inBuffer = new ByteArrayInputStream(raw); + final ObjectInputStream inStream = new ObjectInputStream(inBuffer); + final BasicCookieStore clone = (BasicCookieStore) inStream.readObject(); final List expected = orig.getCookies(); final List clones = clone.getCookies(); Assert.assertNotNull(expected); diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestBasicResponseHandler.java b/httpclient/src/test/java/org/apache/http/impl/client/TestBasicResponseHandler.java index 8a4f0ed61d..8bb0a438a7 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/TestBasicResponseHandler.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/TestBasicResponseHandler.java @@ -61,10 +61,10 @@ public void testSuccessfulResponse() throws Exception { @Test public void testUnsuccessfulResponse() throws Exception { - final InputStream instream = Mockito.mock(InputStream.class); + final InputStream inStream = Mockito.mock(InputStream.class); final HttpEntity entity = Mockito.mock(HttpEntity.class); Mockito.when(entity.isStreaming()).thenReturn(true); - Mockito.when(entity.getContent()).thenReturn(instream); + Mockito.when(entity.getContent()).thenReturn(inStream); final StatusLine sl = new BasicStatusLine(HttpVersion.HTTP_1_1, 404, "Not Found"); final HttpResponse response = Mockito.mock(HttpResponse.class); Mockito.when(response.getStatusLine()).thenReturn(sl); @@ -79,7 +79,7 @@ public void testUnsuccessfulResponse() throws Exception { Assert.assertEquals("Not Found", ex.getMessage()); } Mockito.verify(entity).getContent(); - Mockito.verify(instream).close(); + Mockito.verify(inStream).close(); } } diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestIdleConnectionEvictor.java b/httpclient/src/test/java/org/apache/http/impl/client/TestIdleConnectionEvictor.java index 135f634972..da0d9bd998 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/TestIdleConnectionEvictor.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/TestIdleConnectionEvictor.java @@ -32,6 +32,7 @@ import org.apache.http.conn.HttpClientConnectionManager; import org.junit.Assert; import org.junit.Test; +import org.mockito.Matchers; import org.mockito.Mockito; /** @@ -68,7 +69,7 @@ public void testEvictExpiredOnly() throws Exception { Thread.sleep(1000); Mockito.verify(cm, Mockito.atLeast(1)).closeExpiredConnections(); - Mockito.verify(cm, Mockito.never()).closeIdleConnections(Mockito.anyLong(), Mockito.any()); + Mockito.verify(cm, Mockito.never()).closeIdleConnections(Matchers.anyLong(), Matchers.any()); Assert.assertTrue(connectionEvictor.isRunning()); diff --git a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestAbortHandling.java b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestAbortHandling.java index 282e11b963..67f058dede 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestAbortHandling.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestAbortHandling.java @@ -373,20 +373,19 @@ public boolean cancel() { @Override public HttpClientConnection get( final long timeout, - final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException { + final TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException { connLatch.countDown(); // notify waiter that we're getting a connection // zero usually means sleep forever, but CountDownLatch doesn't interpret it that way. - if(!awaitLatch.await(timeout > 0 ? timeout : Integer.MAX_VALUE, tunit)) { + if(!awaitLatch.await(timeout > 0 ? timeout : Integer.MAX_VALUE, timeUnit)) { throw new ConnectionPoolTimeoutException(); } return Mockito.mock(HttpClientConnection.class); } }; - } else { - return super.requestConnection(route, state); } + return super.requestConnection(route, state); } } @@ -401,7 +400,7 @@ public ConMan(final CountDownLatch connLatch, final CountDownLatch awaitLatch) { } @Override - public void closeIdleConnections(final long idletime, final TimeUnit tunit) { + public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) { throw new UnsupportedOperationException("just a mockup"); } @@ -411,7 +410,7 @@ public void closeExpiredConnections() { } public HttpClientConnection getConnection(final HttpRoute route, - final long timeout, final TimeUnit tunit) { + final long timeout, final TimeUnit timeUnit) { throw new UnsupportedOperationException("just a mockup"); } @@ -433,11 +432,11 @@ public boolean cancel() { @Override public HttpClientConnection get( final long timeout, - final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException { + final TimeUnit timeUnit) throws InterruptedException, ConnectionPoolTimeoutException { connLatch.countDown(); // notify waiter that we're getting a connection // zero usually means sleep forever, but CountDownLatch doesn't interpret it that way. - if(!awaitLatch.await(timeout > 0 ? timeout : Integer.MAX_VALUE, tunit)) { + if(!awaitLatch.await(timeout > 0 ? timeout : Integer.MAX_VALUE, timeUnit)) { throw new ConnectionPoolTimeoutException(); } diff --git a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestConnectionAutoRelease.java b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestConnectionAutoRelease.java index a4de80da2e..63451d4cca 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestConnectionAutoRelease.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestConnectionAutoRelease.java @@ -178,10 +178,10 @@ public void handle( @Override public void writeTo( - final OutputStream outstream) throws IOException { + final OutputStream outStream) throws IOException { final byte[] tmp = new byte[5]; - outstream.write(tmp); - outstream.flush(); + outStream.write(tmp); + outStream.flush(); // do something comletely ugly in order to trigger // MalformedChunkCodingException diff --git a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestMalformedServerResponse.java b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestMalformedServerResponse.java index b18f8fcaa4..9dc8f6d0e0 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/integration/TestMalformedServerResponse.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/integration/TestMalformedServerResponse.java @@ -50,8 +50,8 @@ public class TestMalformedServerResponse extends LocalServerTestBase { static class BrokenServerConnection extends DefaultBHttpServerConnection { - public BrokenServerConnection(final int buffersize) { - super(buffersize); + public BrokenServerConnection(final int bufferSize) { + super(bufferSize); } @Override diff --git a/httpclient/src/test/java/org/apache/http/impl/conn/SessionInputBufferMock.java b/httpclient/src/test/java/org/apache/http/impl/conn/SessionInputBufferMock.java index 15c9f20cef..f1ca2071a7 100644 --- a/httpclient/src/test/java/org/apache/http/impl/conn/SessionInputBufferMock.java +++ b/httpclient/src/test/java/org/apache/http/impl/conn/SessionInputBufferMock.java @@ -45,39 +45,39 @@ public class SessionInputBufferMock extends SessionInputBufferImpl { public static final int BUFFER_SIZE = 16; public SessionInputBufferMock( - final InputStream instream, - final int buffersize, + final InputStream inStream, + final int bufferSize, final MessageConstraints constrains, final CharsetDecoder decoder) { - super(new HttpTransportMetricsImpl(), buffersize, -1, constrains, decoder); - bind(instream); + super(new HttpTransportMetricsImpl(), bufferSize, -1, constrains, decoder); + bind(inStream); } public SessionInputBufferMock( - final InputStream instream, - final int buffersize) { - this(instream, buffersize, null, null); + final InputStream inStream, + final int bufferSize) { + this(inStream, bufferSize, null, null); } public SessionInputBufferMock( final byte[] bytes, - final int buffersize, + final int bufferSize, final MessageConstraints constrains, final CharsetDecoder decoder) { - this(new ByteArrayInputStream(bytes), buffersize, constrains, decoder); + this(new ByteArrayInputStream(bytes), bufferSize, constrains, decoder); } public SessionInputBufferMock( final byte[] bytes, - final int buffersize, + final int bufferSize, final MessageConstraints constrains) { - this(new ByteArrayInputStream(bytes), buffersize, constrains, null); + this(new ByteArrayInputStream(bytes), bufferSize, constrains, null); } public SessionInputBufferMock( final byte[] bytes, - final int buffersize) { - this(new ByteArrayInputStream(bytes), buffersize); + final int bufferSize) { + this(new ByteArrayInputStream(bytes), bufferSize); } public SessionInputBufferMock( diff --git a/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java b/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java index 207cddc30d..da26ebd8bb 100644 --- a/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java +++ b/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java @@ -55,8 +55,8 @@ public void testResponseParsingWithSomeGarbage() throws Exception { "header2: value2\r\n" + "\r\n"; - final SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII); - final HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer); + final SessionInputBuffer inBuffer = new SessionInputBufferMock(s, Consts.ASCII); + final HttpMessageParser parser = new DefaultHttpResponseParser(inBuffer); final HttpResponse response = parser.parse(); Assert.assertNotNull(response); @@ -81,8 +81,8 @@ public void testResponseParsingWithTooMuchGarbage() throws Exception { "header2: value2\r\n" + "\r\n"; - final SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII); - final HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer) { + final SessionInputBuffer inBuffer = new SessionInputBufferMock(s, Consts.ASCII); + final HttpMessageParser parser = new DefaultHttpResponseParser(inBuffer) { @Override protected boolean reject(final CharArrayBuffer line, final int count) { @@ -95,8 +95,8 @@ protected boolean reject(final CharArrayBuffer line, final int count) { @Test(expected=NoHttpResponseException.class) public void testResponseParsingNoResponse() throws Exception { - final SessionInputBuffer inbuffer = new SessionInputBufferMock("", Consts.ASCII); - final HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer); + final SessionInputBuffer inBuffer = new SessionInputBufferMock("", Consts.ASCII); + final HttpMessageParser parser = new DefaultHttpResponseParser(inBuffer); parser.parse(); } @@ -107,8 +107,8 @@ public void testResponseParsingOnlyGarbage() throws Exception { "garbage\r\n" + "more garbage\r\n" + "a lot more garbage\r\n"; - final SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII); - final HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer); + final SessionInputBuffer inBuffer = new SessionInputBufferMock(s, Consts.ASCII); + final HttpMessageParser parser = new DefaultHttpResponseParser(inBuffer); parser.parse(); } diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie.java index c807a2f9cd..d1378b0944 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie.java @@ -75,13 +75,13 @@ public void testSerialization() throws Exception { orig.setPath("/"); orig.setAttribute("attrib", "stuff"); final ByteArrayOutputStream outbuffer = new ByteArrayOutputStream(); - final ObjectOutputStream outstream = new ObjectOutputStream(outbuffer); - outstream.writeObject(orig); - outstream.close(); + final ObjectOutputStream outStream = new ObjectOutputStream(outbuffer); + outStream.writeObject(orig); + outStream.close(); final byte[] raw = outbuffer.toByteArray(); - final ByteArrayInputStream inbuffer = new ByteArrayInputStream(raw); - final ObjectInputStream instream = new ObjectInputStream(inbuffer); - final BasicClientCookie clone = (BasicClientCookie) instream.readObject(); + final ByteArrayInputStream inBuffer = new ByteArrayInputStream(raw); + final ObjectInputStream inStream = new ObjectInputStream(inBuffer); + final BasicClientCookie clone = (BasicClientCookie) inStream.readObject(); Assert.assertEquals(orig.getName(), clone.getName()); Assert.assertEquals(orig.getValue(), clone.getValue()); Assert.assertEquals(orig.getDomain(), clone.getDomain()); diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie2.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie2.java index 9af1608bbc..31fad7db9e 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie2.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicClientCookie2.java @@ -95,13 +95,13 @@ public void testSerialization() throws Exception { orig.setAttribute("attrib", "stuff"); orig.setPorts(new int[] {80, 8080}); final ByteArrayOutputStream outbuffer = new ByteArrayOutputStream(); - final ObjectOutputStream outstream = new ObjectOutputStream(outbuffer); - outstream.writeObject(orig); - outstream.close(); + final ObjectOutputStream outStream = new ObjectOutputStream(outbuffer); + outStream.writeObject(orig); + outStream.close(); final byte[] raw = outbuffer.toByteArray(); - final ByteArrayInputStream inbuffer = new ByteArrayInputStream(raw); - final ObjectInputStream instream = new ObjectInputStream(inbuffer); - final BasicClientCookie2 clone = (BasicClientCookie2) instream.readObject(); + final ByteArrayInputStream inBuffer = new ByteArrayInputStream(raw); + final ObjectInputStream inStream = new ObjectInputStream(inBuffer); + final BasicClientCookie2 clone = (BasicClientCookie2) inStream.readObject(); Assert.assertEquals(orig.getName(), clone.getName()); Assert.assertEquals(orig.getValue(), clone.getValue()); Assert.assertEquals(orig.getDomain(), clone.getDomain()); diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java index fc6adf1670..35753fdba1 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestRFC6265CookieSpec.java @@ -40,6 +40,7 @@ import org.apache.http.message.BasicHeader; import org.junit.Assert; import org.junit.Test; +import org.mockito.Matchers; import org.mockito.Mockito; public class TestRFC6265CookieSpec { @@ -68,8 +69,8 @@ public void testParseCookieBasics() throws Exception { Assert.assertEquals("stuff", clientCookie.getAttribute("this")); Assert.assertEquals(null, clientCookie.getAttribute("that")); - Mockito.verify(h1).parse(Mockito.any(), Mockito.eq("stuff")); - Mockito.verify(h2, Mockito.never()).parse(Mockito.any(), Mockito.anyString()); + Mockito.verify(h1).parse(Matchers.any(), Matchers.eq("stuff")); + Mockito.verify(h2, Mockito.never()).parse(Matchers.any(), Matchers.anyString()); } @Test @@ -315,8 +316,8 @@ public void testParseCookieMultipleAttributes() throws Exception { final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true); cookiespec.parse(header, origin); - Mockito.verify(h1).parse(Mockito.any(), Mockito.eq("morestuff")); - Mockito.verify(h1, Mockito.times(1)).parse(Mockito.any(), Mockito.anyString()); + Mockito.verify(h1).parse(Matchers.any(), Matchers.eq("morestuff")); + Mockito.verify(h1, Mockito.times(1)).parse(Matchers.any(), Matchers.anyString()); } @Test @@ -332,8 +333,8 @@ public void testParseCookieMaxAgeOverExpires() throws Exception { final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true); cookiespec.parse(header, origin); - Mockito.verify(h1, Mockito.never()).parse(Mockito.any(), Mockito.anyString()); - Mockito.verify(h2).parse(Mockito.any(), Mockito.eq("otherstuff")); + Mockito.verify(h1, Mockito.never()).parse(Matchers.any(), Matchers.anyString()); + Mockito.verify(h2).parse(Matchers.any(), Matchers.eq("otherstuff")); } } diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java index 2261da82ba..7de9921e20 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestMainClientExec.java @@ -418,14 +418,14 @@ public void testExecRequestRetryOnAuthChallenge() throws Exception { final HttpClientContext context = new HttpClientContext(); final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test")); final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + final InputStream inStream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); response1.setEntity(EntityBuilder.create() - .setStream(instream1) + .setStream(inStream1) .build()); final HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK"); - final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); + final InputStream inStream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); response2.setEntity(EntityBuilder.create() - .setStream(instream2) + .setStream(inStream2) .build()); Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE); @@ -445,8 +445,8 @@ public void testExecRequestRetryOnAuthChallenge() throws Exception { final CloseableHttpResponse finalResponse = mainClientExec.execute( route, request, context, execAware); Mockito.verify(requestExecutor, Mockito.times(2)).execute(request, managedConn, context); - Mockito.verify(instream1).close(); - Mockito.verify(instream2, Mockito.never()).close(); + Mockito.verify(inStream1).close(); + Mockito.verify(inStream2, Mockito.never()).close(); Assert.assertNotNull(finalResponse); Assert.assertEquals(200, finalResponse.getStatusLine().getStatusCode()); @@ -457,14 +457,14 @@ public void testExecEntityEnclosingRequestRetryOnAuthChallenge() throws Exceptio final HttpRoute route = new HttpRoute(target); final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test")); final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + final InputStream inStream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); response1.setEntity(EntityBuilder.create() - .setStream(instream1) + .setStream(inStream1) .build()); final HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK"); - final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); + final InputStream inStream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); response2.setEntity(EntityBuilder.create() - .setStream(instream2) + .setStream(inStream2) .build()); final AuthState proxyAuthState = new AuthState(); @@ -492,7 +492,7 @@ public void testExecEntityEnclosingRequestRetryOnAuthChallenge() throws Exceptio route, request, context, execAware); Mockito.verify(requestExecutor, Mockito.times(2)).execute(request, managedConn, context); Mockito.verify(managedConn).close(); - Mockito.verify(instream2, Mockito.never()).close(); + Mockito.verify(inStream2, Mockito.never()).close(); Assert.assertNotNull(finalResponse); Assert.assertEquals(200, finalResponse.getStatusLine().getStatusCode()); @@ -505,16 +505,16 @@ public void testExecEntityEnclosingRequest() throws Exception { final HttpRoute route = new HttpRoute(target); final HttpClientContext context = new HttpClientContext(); final HttpPost post = new HttpPost("http://bar/test"); - final InputStream instream0 = new ByteArrayInputStream(new byte[] {1, 2, 3}); + final InputStream inStream0 = new ByteArrayInputStream(new byte[] {1, 2, 3}); post.setEntity(EntityBuilder.create() - .setStream(instream0) + .setStream(inStream0) .build()); final HttpRequestWrapper request = HttpRequestWrapper.wrap(post); final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?"); - final InputStream instream1 = new ByteArrayInputStream(new byte[] {1, 2, 3}); + final InputStream inStream1 = new ByteArrayInputStream(new byte[] {1, 2, 3}); response1.setEntity(EntityBuilder.create() - .setStream(instream1) + .setStream(inStream1) .build()); Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE); @@ -733,9 +733,9 @@ public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengePersistentConnec final HttpClientContext context = new HttpClientContext(); final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test")); final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + final InputStream inStream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); response1.setEntity(EntityBuilder.create() - .setStream(instream1) + .setStream(inStream1) .build()); final HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK"); @@ -756,7 +756,7 @@ public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengePersistentConnec Mockito.verify(connManager).connect(managedConn, route, 0, context); Mockito.verify(connManager).routeComplete(managedConn, route, context); - Mockito.verify(instream1).close(); + Mockito.verify(inStream1).close(); } @Test @@ -766,9 +766,9 @@ public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengeNonPersistentCon final HttpClientContext context = new HttpClientContext(); final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test")); final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + final InputStream inStream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); response1.setEntity(EntityBuilder.create() - .setStream(instream1) + .setStream(inStream1) .build()); final HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK"); @@ -789,7 +789,7 @@ public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengeNonPersistentCon Mockito.verify(connManager).connect(managedConn, route, 0, context); Mockito.verify(connManager).routeComplete(managedConn, route, context); - Mockito.verify(instream1, Mockito.never()).close(); + Mockito.verify(inStream1, Mockito.never()).close(); Mockito.verify(managedConn).close(); } diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java index 5621a3f2c1..a5d0591daf 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestRedirectExec.java @@ -96,15 +96,15 @@ public void testFundamentals() throws Exception { final HttpClientContext context = HttpClientContext.create(); final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + final InputStream inStream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); final HttpEntity entity1 = EntityBuilder.create() - .setStream(instream1) + .setStream(inStream1) .build(); Mockito.when(response1.getEntity()).thenReturn(entity1); final CloseableHttpResponse response2 = Mockito.mock(CloseableHttpResponse.class); - final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + final InputStream inStream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); final HttpEntity entity2 = EntityBuilder.create() - .setStream(instream2) + .setStream(inStream2) .build(); Mockito.when(response2.getEntity()).thenReturn(entity2); final HttpGet redirect = new HttpGet("http://localhost:80/redirect"); @@ -154,9 +154,9 @@ public void testFundamentals() throws Exception { Assert.assertEquals("that", headers[1].getValue()); Mockito.verify(response1, Mockito.times(1)).close(); - Mockito.verify(instream1, Mockito.times(1)).close(); + Mockito.verify(inStream1, Mockito.times(1)).close(); Mockito.verify(response2, Mockito.never()).close(); - Mockito.verify(instream2, Mockito.never()).close(); + Mockito.verify(inStream2, Mockito.never()).close(); } @Test(expected = RedirectException.class) @@ -321,9 +321,9 @@ public void testRedirectProtocolException() throws Exception { final HttpClientContext context = HttpClientContext.create(); final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + final InputStream inStream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); final HttpEntity entity1 = EntityBuilder.create() - .setStream(instream1) + .setStream(inStream1) .build(); Mockito.when(response1.getEntity()).thenReturn(entity1); Mockito.when(requestExecutor.execute( @@ -343,7 +343,7 @@ public void testRedirectProtocolException() throws Exception { try { redirectExec.execute(route, request, context, execAware); } catch (final Exception ex) { - Mockito.verify(instream1).close(); + Mockito.verify(inStream1).close(); Mockito.verify(response1).close(); throw ex; } diff --git a/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java b/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java index 803cb94cd9..b4b2b7799b 100644 --- a/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java +++ b/httpclient/src/test/java/org/apache/http/impl/execchain/TestResponseEntityWrapper.java @@ -41,16 +41,16 @@ @SuppressWarnings("boxing") // test code public class TestResponseEntityWrapper { - private InputStream instream; + private InputStream inStream; private HttpEntity entity; private ConnectionHolder connHolder; private ResponseEntityProxy wrapper; @Before public void setup() throws Exception { - instream = Mockito.mock(InputStream.class); + inStream = Mockito.mock(InputStream.class); entity = Mockito.mock(HttpEntity.class); - Mockito.when(entity.getContent()).thenReturn(instream); + Mockito.when(entity.getContent()).thenReturn(inStream); connHolder = Mockito.mock(ConnectionHolder.class); wrapper = new ResponseEntityProxy(entity, connHolder); } @@ -61,7 +61,7 @@ public void testReusableEntityStreamClosed() throws Exception { Mockito.when(connHolder.isReusable()).thenReturn(true); EntityUtils.consume(wrapper); - Mockito.verify(instream, Mockito.times(1)).close(); + Mockito.verify(inStream, Mockito.times(1)).close(); Mockito.verify(connHolder).releaseConnection(); } @@ -69,7 +69,7 @@ public void testReusableEntityStreamClosed() throws Exception { public void testReusableEntityStreamClosedIOError() throws Exception { Mockito.when(entity.isStreaming()).thenReturn(true); Mockito.when(connHolder.isReusable()).thenReturn(true); - Mockito.doThrow(new IOException()).when(instream).close(); + Mockito.doThrow(new IOException()).when(inStream).close(); try { EntityUtils.consume(wrapper); Assert.fail("IOException expected"); @@ -83,28 +83,28 @@ public void testEntityStreamClosedIOErrorAlreadyReleased() throws Exception { Mockito.when(entity.isStreaming()).thenReturn(true); Mockito.when(connHolder.isReusable()).thenReturn(true); Mockito.when(connHolder.isReleased()).thenReturn(true); - Mockito.doThrow(new SocketException()).when(instream).close(); + Mockito.doThrow(new SocketException()).when(inStream).close(); EntityUtils.consume(wrapper); Mockito.verify(connHolder).close(); } @Test public void testReusableEntityWriteTo() throws Exception { - final OutputStream outstream = Mockito.mock(OutputStream.class); + final OutputStream outStream = Mockito.mock(OutputStream.class); Mockito.when(entity.isStreaming()).thenReturn(true); Mockito.when(connHolder.isReusable()).thenReturn(true); - wrapper.writeTo(outstream); + wrapper.writeTo(outStream); Mockito.verify(connHolder).releaseConnection(); } @Test public void testReusableEntityWriteToIOError() throws Exception { - final OutputStream outstream = Mockito.mock(OutputStream.class); + final OutputStream outStream = Mockito.mock(OutputStream.class); Mockito.when(entity.isStreaming()).thenReturn(true); Mockito.when(connHolder.isReusable()).thenReturn(true); - Mockito.doThrow(new IOException()).when(entity).writeTo(outstream); + Mockito.doThrow(new IOException()).when(entity).writeTo(outStream); try { - wrapper.writeTo(outstream); + wrapper.writeTo(outStream); Assert.fail("IOException expected"); } catch (final IOException ex) { } @@ -114,21 +114,21 @@ public void testReusableEntityWriteToIOError() throws Exception { @Test public void testReusableEntityEndOfStream() throws Exception { - Mockito.when(instream.read()).thenReturn(-1); + Mockito.when(inStream.read()).thenReturn(-1); Mockito.when(entity.isStreaming()).thenReturn(true); Mockito.when(connHolder.isReusable()).thenReturn(true); final InputStream content = wrapper.getContent(); Assert.assertEquals(-1, content.read()); - Mockito.verify(instream).close(); + Mockito.verify(inStream).close(); Mockito.verify(connHolder).releaseConnection(); } @Test public void testReusableEntityEndOfStreamIOError() throws Exception { - Mockito.when(instream.read()).thenReturn(-1); + Mockito.when(inStream.read()).thenReturn(-1); Mockito.when(entity.isStreaming()).thenReturn(true); Mockito.when(connHolder.isReusable()).thenReturn(true); - Mockito.doThrow(new IOException()).when(instream).close(); + Mockito.doThrow(new IOException()).when(inStream).close(); final InputStream content = wrapper.getContent(); try { content.read(); diff --git a/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java b/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java index 071aa87376..dd264ea90c 100644 --- a/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java +++ b/httpmime/src/main/java-deprecated/org/apache/http/entity/mime/MultipartEntity.java @@ -176,8 +176,8 @@ public InputStream getContent() throws IOException, UnsupportedOperationExceptio } @Override - public void writeTo(final OutputStream outstream) throws IOException { - getEntity().writeTo(outstream); + public void writeTo(final OutputStream outStream) throws IOException { + getEntity().writeTo(outStream); } } diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java b/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java index cabb824ae8..e3afe404af 100644 --- a/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java +++ b/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java @@ -102,15 +102,15 @@ public InputStream getContent() throws IOException { } else if (this.contentLength > 25 * 1024) { throw new ContentTooLongException("Content length is too long: " + this.contentLength); } - final ByteArrayOutputStream outstream = new ByteArrayOutputStream(); - writeTo(outstream); - outstream.flush(); - return new ByteArrayInputStream(outstream.toByteArray()); + final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + writeTo(outStream); + outStream.flush(); + return new ByteArrayInputStream(outStream.toByteArray()); } @Override - public void writeTo(final OutputStream outstream) throws IOException { - this.multipart.writeTo(outstream); + public void writeTo(final OutputStream outStream) throws IOException { + this.multipart.writeTo(outStream); } } From 46638fa7e1433f5087ab1cde7652a0c60d8ac75c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 28 Aug 2018 14:19:20 +0200 Subject: [PATCH 198/204] Fixed call to get proxy auth state --- .../org/apache/http/examples/client/ClientConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java index af1c1a5c7a..6134dac067 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java @@ -258,7 +258,7 @@ public InetAddress[] resolve(final String host) throws UnknownHostException { // Target auth state context.getTargetAuthState(); // Proxy auth state - context.getTargetAuthState(); + context.getProxyAuthState(); // Cookie origin context.getCookieOrigin(); // Cookie spec used From 4b894bc18e628a5f1e350448553a541af8ad6df1 Mon Sep 17 00:00:00 2001 From: Vincent Privat Date: Mon, 10 Sep 2018 23:32:51 +0200 Subject: [PATCH 199/204] update JNA from 4.4.0 to 4.5.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1930e5702f..33297087d3 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 4.11 2.5.2 1.10.19 - 4.4.0 + 4.5.2 1 4.5 From 7163bca4679b5f3846badb47da6ac414442d8c94 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Sep 2018 18:44:02 -0600 Subject: [PATCH 200/204] Add org.apache.hc.client5.http.config.RequestConfig.toString() and camcel-case an ivar. --- .../http/client/methods/RequestBuilder.java | 77 ++++++++++++------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java index b630dba945..818ec661a6 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/RequestBuilder.java @@ -72,7 +72,7 @@ public class RequestBuilder { private Charset charset; private ProtocolVersion version; private URI uri; - private HeaderGroup headergroup; + private HeaderGroup headerGroup; private HttpEntity entity; private List parameters; private RequestConfig config; @@ -263,11 +263,11 @@ private RequestBuilder doCopy(final HttpRequest request) { method = request.getRequestLine().getMethod(); version = request.getRequestLine().getProtocolVersion(); - if (headergroup == null) { - headergroup = new HeaderGroup(); + if (headerGroup == null) { + headerGroup = new HeaderGroup(); } - headergroup.clear(); - headergroup.setHeaders(request.getAllHeaders()); + headerGroup.clear(); + headerGroup.setHeaders(request.getAllHeaders()); parameters = null; entity = null; @@ -347,46 +347,46 @@ public RequestBuilder setUri(final String uri) { } public Header getFirstHeader(final String name) { - return headergroup != null ? headergroup.getFirstHeader(name) : null; + return headerGroup != null ? headerGroup.getFirstHeader(name) : null; } public Header getLastHeader(final String name) { - return headergroup != null ? headergroup.getLastHeader(name) : null; + return headerGroup != null ? headerGroup.getLastHeader(name) : null; } public Header[] getHeaders(final String name) { - return headergroup != null ? headergroup.getHeaders(name) : null; + return headerGroup != null ? headerGroup.getHeaders(name) : null; } public RequestBuilder addHeader(final Header header) { - if (headergroup == null) { - headergroup = new HeaderGroup(); + if (headerGroup == null) { + headerGroup = new HeaderGroup(); } - headergroup.addHeader(header); + headerGroup.addHeader(header); return this; } public RequestBuilder addHeader(final String name, final String value) { - if (headergroup == null) { - headergroup = new HeaderGroup(); + if (headerGroup == null) { + headerGroup = new HeaderGroup(); } - this.headergroup.addHeader(new BasicHeader(name, value)); + this.headerGroup.addHeader(new BasicHeader(name, value)); return this; } public RequestBuilder removeHeader(final Header header) { - if (headergroup == null) { - headergroup = new HeaderGroup(); + if (headerGroup == null) { + headerGroup = new HeaderGroup(); } - headergroup.removeHeader(header); + headerGroup.removeHeader(header); return this; } public RequestBuilder removeHeaders(final String name) { - if (name == null || headergroup == null) { + if (name == null || headerGroup == null) { return this; } - for (final HeaderIterator i = headergroup.iterator(); i.hasNext(); ) { + for (final HeaderIterator i = headerGroup.iterator(); i.hasNext(); ) { final Header header = i.nextHeader(); if (name.equalsIgnoreCase(header.getName())) { i.remove(); @@ -396,18 +396,18 @@ public RequestBuilder removeHeaders(final String name) { } public RequestBuilder setHeader(final Header header) { - if (headergroup == null) { - headergroup = new HeaderGroup(); + if (headerGroup == null) { + headerGroup = new HeaderGroup(); } - this.headergroup.updateHeader(header); + this.headerGroup.updateHeader(header); return this; } public RequestBuilder setHeader(final String name, final String value) { - if (headergroup == null) { - headergroup = new HeaderGroup(); + if (headerGroup == null) { + headerGroup = new HeaderGroup(); } - this.headergroup.updateHeader(new BasicHeader(name, value)); + this.headerGroup.updateHeader(new BasicHeader(name, value)); return this; } @@ -482,8 +482,8 @@ public HttpUriRequest build() { } result.setProtocolVersion(this.version); result.setURI(uriNotNull); - if (this.headergroup != null) { - result.setHeaders(this.headergroup.getAllHeaders()); + if (this.headerGroup != null) { + result.setHeaders(this.headerGroup.getAllHeaders()); } result.setConfig(this.config); return result; @@ -521,4 +521,27 @@ public String getMethod() { } + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("RequestBuilder [method="); + builder.append(method); + builder.append(", charset="); + builder.append(charset); + builder.append(", version="); + builder.append(version); + builder.append(", uri="); + builder.append(uri); + builder.append(", headerGroup="); + builder.append(headerGroup); + builder.append(", entity="); + builder.append(entity); + builder.append(", parameters="); + builder.append(parameters); + builder.append(", config="); + builder.append(config); + builder.append("]"); + return builder.toString(); + } + } From e1a0227cfd9dfcaf8f02fa80212a46f7bca04728 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 29 Oct 2018 15:43:18 +0100 Subject: [PATCH 201/204] HTTPCORE-561: added SSLSocket timeout test --- .../http/conn/ssl/TestSSLSocketFactory.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java b/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java index 094135672f..c6ff47f4d3 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/TestSSLSocketFactory.java @@ -28,8 +28,10 @@ package org.apache.http.conn.ssl; import java.io.IOException; +import java.io.InputStream; import java.net.InetSocketAddress; import java.net.Socket; +import java.net.SocketTimeoutException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -53,6 +55,7 @@ import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContexts; +import org.hamcrest.CoreMatchers; import org.junit.After; import org.junit.Assert; import org.junit.Test; @@ -341,4 +344,34 @@ public void initialize(final SSLServerSocket socket) throws SSLException { final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); } + + @Test + public void testSSLTimeout() throws Exception { + // @formatter:off + this.server = ServerBootstrap.bootstrap() + .setServerInfo(LocalServerTestBase.ORIGIN) + .setSslContext(SSLTestContexts.createServerSSLContext()) + .create(); + // @formatter:on + this.server.start(); + + final HttpContext context = new BasicHttpContext(); + final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( + SSLTestContexts.createClientSSLContext()); + final Socket socket = socketFactory.createSocket(context); + final InetSocketAddress remoteAddress = new InetSocketAddress("localhost", this.server.getLocalPort()); + final HttpHost target = new HttpHost("localhost", this.server.getLocalPort(), "https"); + final Socket sslSocket = socketFactory.connectSocket(0, socket, target, remoteAddress, null, context); + final InputStream inputStream = sslSocket.getInputStream(); + try { + sslSocket.setSoTimeout(1); + inputStream.read(); + Assert.fail("SocketTimeoutException expected"); + } catch (final SocketTimeoutException ex){ + Assert.assertThat(sslSocket.isClosed(), CoreMatchers.equalTo(false)); + Assert.assertThat(socket.isClosed(), CoreMatchers.equalTo(false)); + } finally { + inputStream.close(); + } + } } From c04ffa17ced5798468682f2e27314ad7d02188af Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 3 Nov 2018 11:34:35 +0100 Subject: [PATCH 202/204] Added missing @deprecated javadoc tags; fixed style check violations --- .../cache/ehcache/TestEhcacheHttpCacheStorage.java | 2 +- .../OSGI-INF/metatype/metatype.properties | 2 +- .../http/impl/auth/win/WindowsNegotiateScheme.java | 3 +++ .../apache/http/client/protocol/ClientContext.java | 5 ----- .../client/protocol/RequestAuthenticationBase.java | 3 +++ .../impl/client/CloseableHttpResponseProxy.java | 2 +- .../http/impl/client/DefaultRequestDirector.java | 7 +------ .../http/impl/cookie/BestMatchSpecFactory.java | 2 +- .../methods/AbstractExecutionAwareRequest.java | 6 ++++++ .../apache/http/client/utils/URLEncodedUtils.java | 1 + .../http/conn/scheme/SocketFactoryAdaptor.java | 3 +++ .../http/conn/ssl/SSLConnectionSocketFactory.java | 9 +++++++++ .../org/apache/http/impl/auth/NTLMEngineImpl.java | 14 ++++++++++---- .../http/impl/execchain/HttpResponseProxy.java | 2 -- .../http/impl/execchain/RequestEntityProxy.java | 1 - .../http/impl/execchain/ResponseEntityProxy.java | 1 - .../apache/http/conn/ssl/TestHostnameVerifier.java | 2 ++ .../apache/http/impl/auth/TestRFC2617Scheme.java | 1 - .../org/apache/http/entity/mime/version.properties | 2 +- 19 files changed, 43 insertions(+), 25 deletions(-) diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheHttpCacheStorage.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheHttpCacheStorage.java index ee91cecc4d..a1366e8a1f 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheHttpCacheStorage.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheHttpCacheStorage.java @@ -74,7 +74,7 @@ public void testCachePut() throws IOException { impl.putEntry(key, value); verify(mockSerializer).writeTo(same(value), isA(OutputStream.class)); - verify(mockCache).put(e);; + verify(mockCache).put(e); } @Test diff --git a/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties b/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties index 30e35f2606..4817615448 100644 --- a/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties +++ b/httpclient-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties @@ -14,7 +14,7 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. # proxyconfigurator.name = Apache HTTP Components Proxy Configurator diff --git a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java index 333458bd5e..141df87a76 100644 --- a/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java +++ b/httpclient-win/src/main/java/org/apache/http/impl/auth/win/WindowsNegotiateScheme.java @@ -305,6 +305,9 @@ public boolean isComplete() { return !continueNeeded; } + /** + * @deprecated Use {@link #authenticate(Credentials, HttpRequest, HttpContext)} + */ @Override @Deprecated public Header authenticate( diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContext.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContext.java index 4794f612a2..e59334b896 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContext.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/ClientContext.java @@ -50,7 +50,6 @@ public interface ClientContext { * Attribute name of a {@link org.apache.http.conn.scheme.Scheme} * object that represents the actual protocol scheme registry. */ - @Deprecated public static final String SCHEME_REGISTRY = "http.scheme-registry"; /** @@ -101,10 +100,6 @@ public interface ClientContext { */ public static final String PROXY_AUTH_STATE = "http.auth.proxy-scope"; - /** - * @deprecated (4.1) do not use - */ - @Deprecated public static final String AUTH_SCHEME_PREF = "http.auth.scheme-pref"; /** diff --git a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestAuthenticationBase.java b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestAuthenticationBase.java index bec0069b26..34e923b9cd 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestAuthenticationBase.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/client/protocol/RequestAuthenticationBase.java @@ -43,6 +43,9 @@ import org.apache.http.protocol.HttpContext; import org.apache.http.util.Asserts; +/** + * @deprecated Do not use. + */ @Deprecated abstract class RequestAuthenticationBase implements HttpRequestInterceptor { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java index 649d359276..da67b7e4b6 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/CloseableHttpResponseProxy.java @@ -40,7 +40,7 @@ import org.apache.http.util.EntityUtils; /** - * @since 4.3 + * @deprecated Do not use. */ @Deprecated class CloseableHttpResponseProxy implements InvocationHandler { diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java index 45cb9988ef..25028744dd 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/client/DefaultRequestDirector.java @@ -128,7 +128,7 @@ * * @since 4.0 * - * @deprecated (4.3) + * @deprecated Do not use. */ @Deprecated public class DefaultRequestDirector implements RequestDirector { @@ -157,21 +157,18 @@ public class DefaultRequestDirector implements RequestDirector { protected final HttpRequestRetryHandler retryHandler; /** The redirect handler. */ - @Deprecated protected final RedirectHandler redirectHandler; /** The redirect strategy. */ protected final RedirectStrategy redirectStrategy; /** The target authentication handler. */ - @Deprecated protected final AuthenticationHandler targetAuthHandler; /** The target authentication handler. */ protected final AuthenticationStrategy targetAuthStrategy; /** The proxy authentication handler. */ - @Deprecated protected final AuthenticationHandler proxyAuthHandler; /** The proxy authentication handler. */ @@ -200,7 +197,6 @@ public class DefaultRequestDirector implements RequestDirector { private HttpHost virtualHost; - @Deprecated public DefaultRequestDirector( final HttpRequestExecutor requestExec, final ClientConnectionManager conman, @@ -224,7 +220,6 @@ public DefaultRequestDirector( } - @Deprecated public DefaultRequestDirector( final Log log, final HttpRequestExecutor requestExec, diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java index e87f3d018d..cf8564f435 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/BestMatchSpecFactory.java @@ -55,7 +55,7 @@ public class BestMatchSpecFactory implements CookieSpecFactory, CookieSpecProvid public BestMatchSpecFactory(final String[] datepatterns, final boolean oneHeader) { super(); - this.cookieSpec = new BestMatchSpec(datepatterns, oneHeader);; + this.cookieSpec = new BestMatchSpec(datepatterns, oneHeader); } public BestMatchSpecFactory() { diff --git a/httpclient/src/main/java/org/apache/http/client/methods/AbstractExecutionAwareRequest.java b/httpclient/src/main/java/org/apache/http/client/methods/AbstractExecutionAwareRequest.java index 9d2facf2ee..e433e9a849 100644 --- a/httpclient/src/main/java/org/apache/http/client/methods/AbstractExecutionAwareRequest.java +++ b/httpclient/src/main/java/org/apache/http/client/methods/AbstractExecutionAwareRequest.java @@ -50,6 +50,9 @@ protected AbstractExecutionAwareRequest() { this.cancellableRef = new AtomicReference(null); } + /** + * @deprecated Use {@link #setCancellable(Cancellable)} + */ @Override @Deprecated public void setConnectionRequest(final ClientConnectionRequest connRequest) { @@ -64,6 +67,9 @@ public boolean cancel() { }); } + /** + * @deprecated Use {@link #setCancellable(Cancellable)} + */ @Override @Deprecated public void setReleaseTrigger(final ConnectionReleaseTrigger releaseTrigger) { diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java index 0397cc4f2d..11b462a6e0 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URLEncodedUtils.java @@ -72,6 +72,7 @@ public class URLEncodedUtils { /** * @deprecated 4.5 Use {@link #parse(URI, Charset)} */ + @Deprecated public static List parse(final URI uri, final String charsetName) { return parse(uri, charsetName != null ? Charset.forName(charsetName) : null); } diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java b/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java index 65a160b9b3..e89516f9dc 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/SocketFactoryAdaptor.java @@ -37,6 +37,9 @@ import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; +/** + * @deprecated Do not use. + */ @Deprecated class SocketFactoryAdaptor implements SocketFactory { diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java index 6ec4412f96..a3cc972d0d 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLConnectionSocketFactory.java @@ -142,14 +142,23 @@ public class SSLConnectionSocketFactory implements LayeredConnectionSocketFactor public static final String SSL = "SSL"; public static final String SSLV2 = "SSLv2"; + /** + * @deprecated Use {@link AllowAllHostnameVerifier#INSTANCE}. + */ @Deprecated public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = AllowAllHostnameVerifier.INSTANCE; + /** + * @deprecated Use {@link BrowserCompatHostnameVerifier#INSTANCE}. + */ @Deprecated public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER = BrowserCompatHostnameVerifier.INSTANCE; + /** + * @deprecated Use {@link StrictHostnameVerifier#INSTANCE}. + */ @Deprecated public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER = StrictHostnameVerifier.INSTANCE; diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java index e642615e27..92a0ecc201 100644 --- a/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java @@ -27,20 +27,20 @@ package org.apache.http.impl.auth; import java.nio.charset.Charset; -import org.apache.http.Consts; import java.security.Key; import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; import java.util.Arrays; import java.util.Locale; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.Certificate; import org.apache.commons.codec.binary.Base64; +import org.apache.http.Consts; /** * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM @@ -289,6 +289,9 @@ protected static class CipherGen { protected byte[] ntlm2SessionResponseUserSessionKey = null; protected byte[] lanManagerSessionKey = null; + /** + * @deprecated Use {@link CipherGen#CipherGen(Random, long, String, String, String, byte[], String, byte[], byte[], byte[], byte[], byte[])} + */ @Deprecated public CipherGen(final String domain, final String user, final String password, final byte[] challenge, final String target, final byte[] targetInformation, @@ -320,6 +323,9 @@ public CipherGen(final Random random, final long currentTime, this.timestamp = timestamp; } + /** + * @deprecated Use {@link CipherGen#CipherGen(Random, long, String, String, String, byte[], String, byte[], byte[], byte[], byte[], byte[])} + */ @Deprecated public CipherGen(final String domain, final String user, diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java index 533eb704fc..6c2ff615b2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/HttpResponseProxy.java @@ -189,13 +189,11 @@ public HeaderIterator headerIterator(final String name) { } @Override - @Deprecated public HttpParams getParams() { return original.getParams(); } @Override - @Deprecated public void setParams(final HttpParams params) { original.setParams(params); } diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java index e5bba360cf..b70d8166ea 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/RequestEntityProxy.java @@ -127,7 +127,6 @@ public boolean isStreaming() { } @Override - @Deprecated public void consumeContent() throws IOException { consumed = true; original.consumeContent(); diff --git a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java index 47c5ac9ed5..ad4b877d4c 100644 --- a/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java +++ b/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java @@ -87,7 +87,6 @@ public InputStream getContent() throws IOException { return new EofSensorInputStream(this.wrappedEntity.getContent(), this); } - @Deprecated @Override public void consumeContent() throws IOException { releaseConnection(); diff --git a/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java b/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java index d04b7cab31..e291691f2e 100644 --- a/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java +++ b/httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java @@ -40,6 +40,8 @@ /** * Unit tests for deprecated {@link X509HostnameVerifier} implementations. + * + * @deprecated Tests deprecated code. */ @Deprecated public class TestHostnameVerifier { diff --git a/httpclient/src/test/java/org/apache/http/impl/auth/TestRFC2617Scheme.java b/httpclient/src/test/java/org/apache/http/impl/auth/TestRFC2617Scheme.java index dc5e8c207d..5c33703318 100644 --- a/httpclient/src/test/java/org/apache/http/impl/auth/TestRFC2617Scheme.java +++ b/httpclient/src/test/java/org/apache/http/impl/auth/TestRFC2617Scheme.java @@ -61,7 +61,6 @@ public TestAuthScheme(final Charset charset) { } @Override - @Deprecated public Header authenticate( final Credentials credentials, final HttpRequest request) throws AuthenticationException { diff --git a/httpmime/src/main/resources/org/apache/http/entity/mime/version.properties b/httpmime/src/main/resources/org/apache/http/entity/mime/version.properties index 9e330be7e5..13e3594819 100644 --- a/httpmime/src/main/resources/org/apache/http/entity/mime/version.properties +++ b/httpmime/src/main/resources/org/apache/http/entity/mime/version.properties @@ -14,7 +14,7 @@ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. # info.module = HttpMime info.release = ${pom.version} From c4d6b3fe59f39b3426bbb30782e872f96ebfe345 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 3 Nov 2018 11:35:58 +0100 Subject: [PATCH 203/204] Upgraded HttpComponents Parent to version 11 --- httpclient-cache/pom.xml | 1 - httpclient/pom.xml | 2 -- httpmime/pom.xml | 1 - pom.xml | 11 +---------- 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/httpclient-cache/pom.xml b/httpclient-cache/pom.xml index 89dc1c3eaa..ee359c92b0 100644 --- a/httpclient-cache/pom.xml +++ b/httpclient-cache/pom.xml @@ -112,7 +112,6 @@ org.codehaus.mojo build-helper-maven-plugin - 1.8 add-source diff --git a/httpclient/pom.xml b/httpclient/pom.xml index fc2c29e937..9a74b4f6da 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -80,7 +80,6 @@ org.codehaus.mojo build-helper-maven-plugin - 1.8 add-source @@ -99,7 +98,6 @@ com.googlecode.maven-download-plugin download-maven-plugin - 1.2.0 download-public-suffix-list diff --git a/httpmime/pom.xml b/httpmime/pom.xml index eabfda5d62..113249debe 100644 --- a/httpmime/pom.xml +++ b/httpmime/pom.xml @@ -73,7 +73,6 @@ org.codehaus.mojo build-helper-maven-plugin - 1.8 add-source diff --git a/pom.xml b/pom.xml index 33297087d3..d01aee3041 100644 --- a/pom.xml +++ b/pom.xml @@ -27,8 +27,7 @@ org.apache.httpcomponents httpcomponents-parent - 10 - ../httpcomponents-parent/pom.xml + 11 4.0.0 httpcomponents-client @@ -298,14 +297,6 @@ org.apache.maven.plugins maven-checkstyle-plugin - 2.9.1 - - - org.apache.httpcomponents - hc-stylecheck - ${hc.stylecheck.version} - - UTF-8 From e4ac7db52f274648ec7296d810065b412ad0cdba Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 3 Nov 2018 14:22:29 +0100 Subject: [PATCH 204/204] Upgraded download-maven-plugin to version 1.2.1 --- httpclient/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 9a74b4f6da..9c2f634bde 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -98,6 +98,7 @@ com.googlecode.maven-download-plugin download-maven-plugin + 1.2.1 download-public-suffix-list