diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2023-01-26 09:20:12 +0100 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2023-01-26 09:24:36 +0100 |
commit | dec5fd736f9d3b02f4885407ae8def2360846014 (patch) | |
tree | a5237dc3fbf991b41b7313e96d53d1ccc41f0361 | |
parent | b6e0d375b0f4c3096cd9299e81154451e8387006 (diff) |
Revert apache 5.1 -> 5.2
27 files changed, 115 insertions, 170 deletions
diff --git a/cloud-tenant-base-dependencies-enforcer/pom.xml b/cloud-tenant-base-dependencies-enforcer/pom.xml index 5e5325fd5ad..4e664934ef9 100644 --- a/cloud-tenant-base-dependencies-enforcer/pom.xml +++ b/cloud-tenant-base-dependencies-enforcer/pom.xml @@ -24,8 +24,8 @@ <bouncycastle.version>1.72</bouncycastle.version> <commons-codec.version>1.15</commons-codec.version> <felix.version>7.0.1</felix.version> - <httpclient5.version>5.2.1</httpclient5.version> - <httpcore5.version>5.2.1</httpcore5.version> + <httpclient5.version>5.1.4</httpclient5.version> + <httpcore5.version>5.1.5</httpcore5.version> <httpclient.version>4.5.14</httpclient.version> <httpcore.version>4.4.16</httpcore.version> <junit5.version>5.8.1</junit5.version> <!-- TODO: in parent this is named 'junit.version' --> diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigVerification.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigVerification.java index bb864fa1708..45a12223b44 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigVerification.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigVerification.java @@ -8,6 +8,7 @@ import com.yahoo.slime.SlimeUtils; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager; import java.io.IOException; import java.util.ArrayDeque; @@ -38,7 +39,7 @@ public class ConfigVerification { for (String arg : args) { configservers.add(prefix + arg + ":" + port + "/config/v2/tenant/" + tenant + "/application/" + appName + "/environment/" + environment + "/region/" + region + "/instance/" + instance + "/?recursive=true"); } - try (CloseableHttpClient httpClient = VespaHttpClientBuilder.custom().buildClient()) { + try (CloseableHttpClient httpClient = VespaHttpClientBuilder.create(BasicHttpClientConnectionManager::new).build()) { System.exit(compareConfigs(listConfigs(configservers, httpClient), httpClient)); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java index ca06fe202d9..b11355df689 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java @@ -214,7 +214,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye public static class Builder { private TenantRepository tenantRepository; private Optional<Provisioner> hostProvisioner; - private HttpProxy httpProxy = new HttpProxy(new SimpleHttpFetcher(Duration.ofSeconds(30))); + private HttpProxy httpProxy = new HttpProxy(new SimpleHttpFetcher()); private Clock clock = Clock.systemUTC(); private ConfigserverConfig configserverConfig = new ConfigserverConfig.Builder().build(); private Orchestrator orchestrator; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java index 132d3d913e7..b7b509c899c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java @@ -14,7 +14,6 @@ import com.yahoo.config.model.api.ServiceInfo; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; @@ -285,6 +284,7 @@ public class ConfigConvergenceChecker extends AbstractComponent { return RequestConfig.custom() .setConnectionRequestTimeout(Timeout.ofSeconds(1)) .setResponseTimeout(Timeout.ofMilliseconds(timeout.toMillis())) + .setConnectTimeout(Timeout.ofSeconds(1)) .build(); } @@ -294,10 +294,7 @@ public class ConfigConvergenceChecker extends AbstractComponent { PoolingAsyncClientConnectionManagerBuilder.create() .setMaxConnTotal(100) .setMaxConnPerRoute(10) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setTimeToLive(TimeValue.ofMilliseconds(1)) - .setConnectTimeout(Timeout.ofSeconds(1)) - .build()) + .setConnectionTimeToLive(TimeValue.ofMilliseconds(1)) .setTlsStrategy(tlsStrategy) .build()) .setIOReactorConfig(IOReactorConfig.custom() diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/DefaultClusterReindexingStatusClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/DefaultClusterReindexingStatusClient.java index 89c57dd6e0e..b2672f7ad85 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/DefaultClusterReindexingStatusClient.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/DefaultClusterReindexingStatusClient.java @@ -146,7 +146,6 @@ public class DefaultClusterReindexingStatusClient implements ClusterReindexingSt } - @SuppressWarnings("deprecation") private static CloseableHttpAsyncClient createHttpClient() { return VespaAsyncHttpClientBuilder .create() diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java index 0aa86ab211a..1168898d126 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java @@ -21,15 +21,18 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; -import java.time.Duration; import java.util.List; +import java.util.logging.Logger; import static java.nio.charset.StandardCharsets.UTF_8; public class HttpProxy { + + private static final Logger logger = Logger.getLogger(HttpProxy.class.getName()); + private final HttpFetcher fetcher; - @Inject public HttpProxy(NodeHostnameVerifier verifier) { this(new SimpleHttpFetcher(Duration.ofSeconds(30), verifier)); } + @Inject public HttpProxy(NodeHostnameVerifier verifier) { this(new SimpleHttpFetcher(verifier)); } public HttpProxy(HttpFetcher fetcher) { this.fetcher = fetcher; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/LogRetriever.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/LogRetriever.java index 5d1d8da3648..3be99ab8393 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/LogRetriever.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/LogRetriever.java @@ -18,9 +18,8 @@ import java.util.Optional; */ public class LogRetriever { - private final CloseableHttpClient httpClient = VespaHttpClientBuilder.custom().buildClient(); + private final CloseableHttpClient httpClient = VespaHttpClientBuilder.create().build(); - @SuppressWarnings("deprecation") public HttpResponse getLogs(String logServerUri, Optional<Instant> deployTime) { HttpGet get = new HttpGet(logServerUri); try { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SecretStoreValidator.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SecretStoreValidator.java index 58d2e6a2c90..17f33e477ec 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SecretStoreValidator.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SecretStoreValidator.java @@ -33,7 +33,7 @@ public class SecretStoreValidator { private static final String PROTOCOL = "http://"; private static final String AWS_PARAMETER_VALIDATION_HANDLER_POSTFIX = ":4080/validate-secret-store"; private final SecretStore secretStore; - private final CloseableHttpClient httpClient = VespaHttpClientBuilder.custom().buildClient(); + private final CloseableHttpClient httpClient = VespaHttpClientBuilder.create().build(); public SecretStoreValidator(SecretStore secretStore) { this.secretStore = secretStore; @@ -58,7 +58,6 @@ public class SecretStoreValidator { return URI.create(PROTOCOL + hostname + AWS_PARAMETER_VALIDATION_HANDLER_POSTFIX); } - @SuppressWarnings("deprecation") private HttpResponse postRequest(URI uri, Slime slime) { var postRequest = new HttpPost(uri); var data = uncheck(() -> SlimeUtils.toJsonBytes(slime)); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SimpleHttpFetcher.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SimpleHttpFetcher.java index 25d87b5c940..a8dfe3700e7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SimpleHttpFetcher.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SimpleHttpFetcher.java @@ -8,13 +8,14 @@ import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.util.Timeout; import java.io.IOException; import java.net.SocketTimeoutException; import java.net.URI; -import java.time.Duration; import java.util.logging.Level; import java.util.logging.Logger; @@ -23,24 +24,23 @@ public class SimpleHttpFetcher implements HttpFetcher { private final CloseableHttpClient client; - public SimpleHttpFetcher(Duration connectTimeout) { this(connectTimeout, null); } + public SimpleHttpFetcher() { this(null); } - public SimpleHttpFetcher(Duration connectTimeout, NodeHostnameVerifier verifier) { - VespaHttpClientBuilder builder = VespaHttpClientBuilder.custom().connectTimeout(Timeout.of(connectTimeout)); - if (verifier != null) { - builder.hostnameVerifier(verifier::verify); - } - this.client = builder.buildClient(); + public SimpleHttpFetcher(NodeHostnameVerifier verifier) { + HttpClientBuilder b = verifier != null + ? VespaHttpClientBuilder.create(PoolingHttpClientConnectionManager::new, verifier::verify) + : VespaHttpClientBuilder.create(); + this.client = b.build(); } @Override - @SuppressWarnings("deprecation") public HttpResponse get(Params params, URI url) { try { HttpGet request = new HttpGet(url); request.addHeader("Connection", "Close"); request.setConfig( RequestConfig.custom() + .setConnectTimeout(Timeout.ofMilliseconds(params.readTimeoutMs)) .setResponseTimeout(Timeout.ofMilliseconds(params.readTimeoutMs)) .build()); try (CloseableHttpResponse response = client.execute(request)) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/TesterClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/TesterClient.java index 6393243a92f..69bccfe788d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/TesterClient.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/TesterClient.java @@ -23,7 +23,7 @@ import java.util.logging.Logger; */ public class TesterClient { - private final CloseableHttpClient httpClient = VespaHttpClientBuilder.custom().buildClient(); + private final CloseableHttpClient httpClient = VespaHttpClientBuilder.create().build(); private static final Logger logger = Logger.getLogger(TesterClient.class.getName()); public HttpResponse getStatus(String testerHostname, int port) { @@ -64,7 +64,6 @@ public class TesterClient { return execute(new HttpGet(testerUri), "Failed to get test report"); } - @SuppressWarnings("deprecation") private HttpResponse execute(HttpUriRequest request, String messageIfRequestFails) { logger.log(Level.FINE, () -> "Sending request to tester container " + request.getRequestUri()); try { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterDeploymentMetricsRetriever.java b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterDeploymentMetricsRetriever.java index c9a03e362ee..98f01bada3f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterDeploymentMetricsRetriever.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterDeploymentMetricsRetriever.java @@ -56,13 +56,15 @@ public class ClusterDeploymentMetricsRetriever { private static final ExecutorService executor = Executors.newFixedThreadPool(10, new DaemonThreadFactory("cluster-deployment-metrics-retriever-")); private static final CloseableHttpClient httpClient = - VespaHttpClientBuilder.custom() - .connectTimeout(Timeout.ofSeconds(10)) - .connectionManagerFactory(registry -> new PoolingHttpClientConnectionManager(registry, null, null, TimeValue.ofMinutes(1))) - .apacheBuilder() + VespaHttpClientBuilder + .create(registry -> new PoolingHttpClientConnectionManager(registry, + null, + null, + TimeValue.ofMinutes(1))) .setDefaultRequestConfig( RequestConfig.custom() .setConnectionRequestTimeout(Timeout.ofSeconds(60)) + .setConnectTimeout(Timeout.ofSeconds(10)) .setResponseTimeout(Timeout.ofSeconds(10)) .build()) .build(); @@ -158,7 +160,6 @@ public class ClusterDeploymentMetricsRetriever { return new ClusterInfo(dimensions.field("clusterid").asString(), dimensions.field("clustertype").asString()); } - @SuppressWarnings("deprecation") private static Slime doMetricsRequest(URI hostURI) { HttpGet get = new HttpGet(hostURI); try (CloseableHttpResponse response = httpClient.execute(get)) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterProtonMetricsRetriever.java b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterProtonMetricsRetriever.java index 5f3711e43b6..d6fde04cd71 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterProtonMetricsRetriever.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ClusterProtonMetricsRetriever.java @@ -12,6 +12,7 @@ import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.util.Timeout; @@ -26,15 +27,14 @@ public class ClusterProtonMetricsRetriever { private static final Logger log = Logger.getLogger(ClusterProtonMetricsRetriever.class.getName()); - private static final CloseableHttpClient httpClient = - VespaHttpClientBuilder - .custom() - .connectTimeout(Timeout.ofSeconds(10)) - .apacheBuilder() - .setDefaultRequestConfig(RequestConfig.custom() - .setResponseTimeout(Timeout.ofSeconds(10)) - .build()) - .build(); + private static final CloseableHttpClient httpClient = VespaHttpClientBuilder + .create(PoolingHttpClientConnectionManager::new) + .setDefaultRequestConfig( + RequestConfig.custom() + .setConnectTimeout(Timeout.ofSeconds(10)) + .setResponseTimeout(Timeout.ofSeconds(10)) + .build()) + .build(); public Map<String, ProtonMetricsAggregator> requestMetricsGroupedByCluster(Collection<URI> hosts) { @@ -100,7 +100,6 @@ public class ClusterProtonMetricsRetriever { aggregator.addAll(metrics.field("values")); } - @SuppressWarnings("deprecation") private static Slime doMetricsRequest(URI hostURI) { HttpGet get = new HttpGet(hostURI); try (CloseableHttpResponse response = httpClient.execute(get)) { diff --git a/container-core/src/main/java/com/yahoo/container/handler/metrics/MetricsV2Handler.java b/container-core/src/main/java/com/yahoo/container/handler/metrics/MetricsV2Handler.java index 7c1b0cc3099..b3a2205cc0a 100644 --- a/container-core/src/main/java/com/yahoo/container/handler/metrics/MetricsV2Handler.java +++ b/container-core/src/main/java/com/yahoo/container/handler/metrics/MetricsV2Handler.java @@ -62,9 +62,10 @@ public class MetricsV2Handler extends HttpHandlerBase { } private static CloseableHttpClient createHttpClient() { - return VespaHttpClientBuilder.custom().connectTimeout(HTTP_CONNECT_TIMEOUT, MILLISECONDS).apacheBuilder() + return VespaHttpClientBuilder.create() .setUserAgent("application-metrics-retriever") .setDefaultRequestConfig(RequestConfig.custom() + .setConnectTimeout(HTTP_CONNECT_TIMEOUT, MILLISECONDS) .setResponseTimeout(HTTP_SOCKET_TIMEOUT, MILLISECONDS) .build()) .build(); diff --git a/container-core/src/main/java/com/yahoo/container/handler/metrics/PrometheusV1Handler.java b/container-core/src/main/java/com/yahoo/container/handler/metrics/PrometheusV1Handler.java index 960cb795ad6..3333b3e3090 100644 --- a/container-core/src/main/java/com/yahoo/container/handler/metrics/PrometheusV1Handler.java +++ b/container-core/src/main/java/com/yahoo/container/handler/metrics/PrometheusV1Handler.java @@ -63,9 +63,10 @@ public class PrometheusV1Handler extends HttpHandlerBase { } private static CloseableHttpClient createHttpClient() { - return VespaHttpClientBuilder.custom().connectTimeout(HTTP_CONNECT_TIMEOUT, MILLISECONDS).apacheBuilder() + return VespaHttpClientBuilder.create() .setUserAgent("application-prometheus-receiver") .setDefaultRequestConfig(RequestConfig.custom() + .setConnectTimeout(HTTP_CONNECT_TIMEOUT, MILLISECONDS) .setResponseTimeout(HTTP_SOCKET_TIMEOUT, MILLISECONDS) .build()) .build(); diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java index a91a200f9cc..298f0feb9e6 100644 --- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java +++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java @@ -5,7 +5,6 @@ import org.apache.hc.client5.http.SystemDefaultDnsResolver; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.classic.methods.HttpUriRequest; -import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.entity.GzipCompressingEntity; import org.apache.hc.client5.http.entity.mime.FormBodyPart; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; @@ -72,7 +71,6 @@ public class SimpleHttpClient implements AutoCloseable { new DefaultHostnameVerifier()); PoolingHttpClientConnectionManager connManager = PoolingHttpClientConnectionManagerBuilder.create() .setSSLSocketFactory(sslConnectionFactory) - .setDefaultConnectionConfig(ConnectionConfig.custom().build()) .setDnsResolver(new SystemDefaultDnsResolver() { @Override public InetAddress[] resolve(String host) throws UnknownHostException { @@ -160,7 +158,6 @@ public class SimpleHttpClient implements AutoCloseable { return this; } - @SuppressWarnings("deprecation") public ResponseValidator execute() throws IOException { if (entity != null) { request.setEntity(entity); diff --git a/http-client/src/main/java/ai/vespa/hosted/client/AbstractHttpClient.java b/http-client/src/main/java/ai/vespa/hosted/client/AbstractHttpClient.java index aab4bf710c1..48bbffc7e37 100644 --- a/http-client/src/main/java/ai/vespa/hosted/client/AbstractHttpClient.java +++ b/http-client/src/main/java/ai/vespa/hosted/client/AbstractHttpClient.java @@ -36,6 +36,7 @@ import java.util.logging.Logger; import static java.util.Objects.requireNonNull; import static java.util.logging.Level.FINE; +import static java.util.logging.Level.WARNING; /** * @author jonmv @@ -47,7 +48,6 @@ public abstract class AbstractHttpClient implements HttpClient { public static HttpClient wrapping(CloseableHttpClient client) { return new AbstractHttpClient() { @Override - @SuppressWarnings("deprecation") protected ClassicHttpResponse execute(ClassicHttpRequest request, HttpClientContext context) throws IOException { return client.execute(request, context); } @@ -121,6 +121,7 @@ public abstract class AbstractHttpClient implements HttpClient { Optional<Duration> remaining = builder.deadline.timeLeftOrThrow(); if (remaining.isPresent()) { config = RequestConfig.copy(config) + .setConnectTimeout(min(config.getConnectTimeout(), remaining.get())) .setConnectionRequestTimeout(min(config.getConnectionRequestTimeout(), remaining.get())) .setResponseTimeout(min(config.getResponseTimeout(), remaining.get())) .build(); diff --git a/http-client/src/main/java/ai/vespa/hosted/client/HttpClient.java b/http-client/src/main/java/ai/vespa/hosted/client/HttpClient.java index 2d1e80101cf..10ef20980e6 100644 --- a/http-client/src/main/java/ai/vespa/hosted/client/HttpClient.java +++ b/http-client/src/main/java/ai/vespa/hosted/client/HttpClient.java @@ -38,6 +38,7 @@ public interface HttpClient extends Closeable { RequestConfig defaultRequestConfig = RequestConfig.custom() .setConnectionRequestTimeout(Timeout.ofSeconds(5)) + .setConnectTimeout(Timeout.ofSeconds(5)) .setRedirectsEnabled(false) .build(); diff --git a/http-utils/src/main/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlanner.java b/http-utils/src/main/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlanner.java index 8275098cb8d..962e6b32947 100644 --- a/http-utils/src/main/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlanner.java +++ b/http-utils/src/main/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlanner.java @@ -4,6 +4,7 @@ package ai.vespa.util.http.hc5; import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.routing.HttpRoutePlanner; +import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.protocol.HttpContext; @@ -15,9 +16,8 @@ import org.apache.hc.core5.http.protocol.HttpContext; */ class HttpToHttpsRoutePlanner implements HttpRoutePlanner { - @SuppressWarnings("deprecation") @Override - public HttpRoute determineRoute(HttpHost target, HttpContext context) { + public HttpRoute determineRoute(HttpHost target, HttpContext context) throws HttpException { if ( ! target.getSchemeName().equals("http") && ! target.getSchemeName().equals("https")) throw new IllegalArgumentException("Scheme must be 'http' or 'https' when using HttpToHttpsRoutePlanner, was '" + target.getSchemeName() + "'"); diff --git a/http-utils/src/main/java/ai/vespa/util/http/hc5/VespaHttpClientBuilder.java b/http-utils/src/main/java/ai/vespa/util/http/hc5/VespaHttpClientBuilder.java index 4f2bdfb213e..a33c4c119c2 100644 --- a/http-utils/src/main/java/ai/vespa/util/http/hc5/VespaHttpClientBuilder.java +++ b/http-utils/src/main/java/ai/vespa/util/http/hc5/VespaHttpClientBuilder.java @@ -1,23 +1,18 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package ai.vespa.util.http.hc5; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.client5.http.socket.ConnectionSocketFactory; import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.RegistryBuilder; -import org.apache.hc.core5.util.TimeValue; -import org.apache.hc.core5.util.Timeout; import javax.net.ssl.HostnameVerifier; -import java.util.concurrent.TimeUnit; - import static com.yahoo.security.tls.MixedMode.PLAINTEXT_CLIENT_MIXED_SERVER; import static com.yahoo.security.tls.TransportSecurityUtils.getInsecureMixedMode; import static com.yahoo.security.tls.TransportSecurityUtils.getSystemTlsContext; @@ -25,65 +20,36 @@ import static com.yahoo.security.tls.TransportSecurityUtils.isTransportSecurityE /** * Sync HTTP client builder <em>for internal Vespa communications over http/https.</em> + * * Configures Vespa mTLS and handles TLS mixed mode automatically. - * Custom connection managers must be configured through {@link #connectionManagerFactory(HttpClientConnectionManagerFactory)}. + * Custom connection managers must be configured through {@link #create(HttpClientConnectionManagerFactory)}. * * @author jonmv */ public class VespaHttpClientBuilder { - private HttpClientConnectionManagerFactory connectionManagerFactory = PoolingHttpClientConnectionManager::new; - private HostnameVerifier hostnameVerifier = new NoopHostnameVerifier(); - private boolean rewriteHttpToHttps = true; - private final ConnectionConfig.Builder connectionConfigBuilder = ConnectionConfig.custom(); public interface HttpClientConnectionManagerFactory { - PoolingHttpClientConnectionManager create(Registry<ConnectionSocketFactory> socketFactories); + HttpClientConnectionManager create(Registry<ConnectionSocketFactory> socketFactories); } - private VespaHttpClientBuilder() { + public static HttpClientBuilder create() { + return create(PoolingHttpClientConnectionManager::new); } - public static VespaHttpClientBuilder custom() { - return new VespaHttpClientBuilder(); + public static HttpClientBuilder create(HttpClientConnectionManagerFactory connectionManagerFactory) { + return create(connectionManagerFactory, new NoopHostnameVerifier()); } - public VespaHttpClientBuilder connectionManagerFactory(HttpClientConnectionManagerFactory connectionManagerFactory) { - this.connectionManagerFactory = connectionManagerFactory; - return this; + public static HttpClientBuilder create(HttpClientConnectionManagerFactory connectionManagerFactory, + HostnameVerifier hostnameVerifier) { + return create(connectionManagerFactory, hostnameVerifier, true); } - public VespaHttpClientBuilder hostnameVerifier(HostnameVerifier hostnameVerifier) { - this.hostnameVerifier = hostnameVerifier; - return this; - } - public VespaHttpClientBuilder rewriteHttpToHttps(boolean enable) { - this.rewriteHttpToHttps = enable; - return this; - } - public VespaHttpClientBuilder connectTimeout(long connectTimeout, TimeUnit timeUnit) { - connectionConfigBuilder.setConnectTimeout(connectTimeout, timeUnit); - return this; - } - public VespaHttpClientBuilder connectTimeout(Timeout connectTimeout) { - connectionConfigBuilder.setConnectTimeout(connectTimeout); - return this; - } - public VespaHttpClientBuilder socketTimeout(long connectTimeout, TimeUnit timeUnit) { - connectionConfigBuilder.setConnectTimeout(connectTimeout, timeUnit); - return this; - } - public VespaHttpClientBuilder validateAfterInactivity(TimeValue validateAfterInactivity) { - connectionConfigBuilder.setValidateAfterInactivity(validateAfterInactivity); - return this; - } - public VespaHttpClientBuilder socketTimeout(Timeout connectTimeout) { - connectionConfigBuilder.setConnectTimeout(connectTimeout); - return this; - } - - public HttpClientBuilder apacheBuilder() { + public static HttpClientBuilder create(HttpClientConnectionManagerFactory connectionManagerFactory, + HostnameVerifier hostnameVerifier, + boolean rewriteHttpToHttps) { HttpClientBuilder builder = HttpClientBuilder.create(); - addSslSocketFactory(builder, new HttpClientConnectionManagerFactoryProxy(), hostnameVerifier); + addSslSocketFactory(builder, connectionManagerFactory, hostnameVerifier); if (rewriteHttpToHttps) addHttpsRewritingRoutePlanner(builder); @@ -94,18 +60,6 @@ public class VespaHttpClientBuilder { return builder; } - public CloseableHttpClient buildClient() { - return apacheBuilder().build(); - } - - private class HttpClientConnectionManagerFactoryProxy implements HttpClientConnectionManagerFactory { - @Override - public PoolingHttpClientConnectionManager create(Registry<ConnectionSocketFactory> socketFactories) { - PoolingHttpClientConnectionManager manager = connectionManagerFactory.create(socketFactories); - manager.setDefaultConnectionConfig(connectionConfigBuilder.build()); - return manager; - } - } private static void addSslSocketFactory(HttpClientBuilder builder, HttpClientConnectionManagerFactory connectionManagerFactory, HostnameVerifier hostnameVerifier) { diff --git a/http-utils/src/test/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlannerTest.java b/http-utils/src/test/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlannerTest.java index 9f56f7ebc09..b20d801e39c 100644 --- a/http-utils/src/test/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlannerTest.java +++ b/http-utils/src/test/java/ai/vespa/util/http/hc5/HttpToHttpsRoutePlannerTest.java @@ -4,6 +4,7 @@ package ai.vespa.util.http.hc5; import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.junit.jupiter.api.Test; @@ -17,7 +18,7 @@ public class HttpToHttpsRoutePlannerTest { final HttpToHttpsRoutePlanner planner = new HttpToHttpsRoutePlanner(); @Test - void verifySchemeMustBeHttp() { + void verifySchemeMustBeHttp() throws HttpException { try { planner.determineRoute(new HttpHost("https", "host", 1), new HttpClientContext()); } @@ -27,7 +28,7 @@ public class HttpToHttpsRoutePlannerTest { } @Test - void verifyPortMustBeSet() { + void verifyPortMustBeSet() throws HttpException { try { planner.determineRoute(new HttpHost("http", "host", -1), new HttpClientContext()); } @@ -38,8 +39,7 @@ public class HttpToHttpsRoutePlannerTest { @Test - @SuppressWarnings("deprecation") - void verifyProxyIsDisallowed() { + void verifyProxyIsDisallowed() throws HttpException { HttpClientContext context = new HttpClientContext(); context.setRequestConfig(RequestConfig.custom().setProxy(new HttpHost("proxy")).build()); try { @@ -51,7 +51,7 @@ public class HttpToHttpsRoutePlannerTest { } @Test - void verifySchemeIsRewritten() { + void verifySchemeIsRewritten() throws HttpException { assertEquals(new HttpRoute(new HttpHost("https", "host", 1)), planner.determineRoute(new HttpHost("http", "host", 1), new HttpClientContext())); } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/application/ApplicationMetricsRetriever.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/application/ApplicationMetricsRetriever.java index 3baed3e1b04..d4f04cdb3fc 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/application/ApplicationMetricsRetriever.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/application/ApplicationMetricsRetriever.java @@ -28,6 +28,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.CancellationException; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; import static ai.vespa.metricsproxy.http.ValuesFetcher.defaultMetricsConsumerId; @@ -187,7 +188,6 @@ public class ApplicationMetricsRetriever extends AbstractComponent implements Ru .toList(); } - @SuppressWarnings("deprecation") static CloseableHttpAsyncClient createHttpClient() { return VespaAsyncHttpClientBuilder.create() .setIOReactorConfig(IOReactorConfig.custom() diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/HttpMetricFetcher.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/HttpMetricFetcher.java index 75853ec9eda..790b3298a81 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/HttpMetricFetcher.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/service/HttpMetricFetcher.java @@ -7,6 +7,8 @@ import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.util.Timeout; import java.io.IOException; @@ -44,7 +46,6 @@ public abstract class HttpMetricFetcher { log.log(Level.FINE, () -> "Fetching metrics from " + u + " with timeout " + CONNECTION_TIMEOUT); } - @SuppressWarnings("deprecation") CloseableHttpResponse getResponse() throws IOException { log.log(Level.FINE, () -> "Connecting to url " + url + " for service '" + service + "'"); return httpClient.execute(new HttpGet(url)); @@ -80,13 +81,17 @@ public abstract class HttpMetricFetcher { } private static CloseableHttpClient createHttpClient() { - return VespaHttpClientBuilder.custom() - .connectTimeout(Timeout.ofMilliseconds(CONNECTION_TIMEOUT)) - .socketTimeout(Timeout.ofMilliseconds(CONNECTION_TIMEOUT)) - .apacheBuilder() + return VespaHttpClientBuilder.create(registry -> { + var mgr = new PoolingHttpClientConnectionManager(registry); + mgr.setDefaultSocketConfig(SocketConfig.custom() + .setSoTimeout(Timeout.ofMilliseconds(SOCKET_TIMEOUT)) + .build()); + return mgr; + }) .setUserAgent("metrics-proxy-http-client") .setDefaultRequestConfig(RequestConfig.custom() .setConnectionRequestTimeout(Timeout.ofMilliseconds(SOCKET_TIMEOUT)) + .setConnectTimeout(Timeout.ofMilliseconds(CONNECTION_TIMEOUT)) .setResponseTimeout(Timeout.ofMilliseconds(SOCKET_TIMEOUT)) .build()) .build(); diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/RetryingClusterControllerClientFactory.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/RetryingClusterControllerClientFactory.java index 1546da7d9a8..479d6bfe079 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/RetryingClusterControllerClientFactory.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/RetryingClusterControllerClientFactory.java @@ -8,7 +8,6 @@ import com.yahoo.component.annotation.Inject; import com.yahoo.component.AbstractComponent; import com.yahoo.vespa.applicationmodel.HostName; import org.apache.hc.core5.http.message.BasicHeader; -import org.apache.hc.core5.util.Timeout; import java.io.IOException; import java.util.List; @@ -26,13 +25,10 @@ public class RetryingClusterControllerClientFactory extends AbstractComponent im @Inject public RetryingClusterControllerClientFactory() { - this(AbstractHttpClient.wrapping(VespaHttpClientBuilder - .custom() - .connectTimeout(Timeout.ofSeconds(5)) - .apacheBuilder() - .setUserAgent("orchestrator-cluster-controller-client") - .setDefaultHeaders(List.of(new BasicHeader("Accept", "application/json"))) - .build())); + this(AbstractHttpClient.wrapping(VespaHttpClientBuilder.create() + .setUserAgent("orchestrator-cluster-controller-client") + .setDefaultHeaders(List.of(new BasicHeader("Accept", "application/json"))) + .build())); } RetryingClusterControllerClientFactory(HttpClient client) { diff --git a/parent/pom.xml b/parent/pom.xml index 612ec7aef19..064d64371a7 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -1102,8 +1102,8 @@ <antlr4.version>4.11.1</antlr4.version> <apache.httpclient.version>4.5.14</apache.httpclient.version> <apache.httpcore.version>4.4.16</apache.httpcore.version> - <apache.httpclient5.version>5.2.1</apache.httpclient5.version> <!-- WARNING: sync cloud-tenant-base-dependencies-enforcer/pom.xml --> - <apache.httpcore5.version>5.2.1</apache.httpcore5.version> <!-- WARNING: sync cloud-tenant-base-dependencies-enforcer/pom.xml --> + <apache.httpclient5.version>5.1.4</apache.httpclient5.version> <!-- WARNING: sync cloud-tenant-base-dependencies-enforcer/pom.xml --> + <apache.httpcore5.version>5.1.5</apache.httpcore5.version> <!-- WARNING: sync cloud-tenant-base-dependencies-enforcer/pom.xml --> <asm.version>9.3</asm.version> <!-- Athenz dependencies. Make sure these dependencies match those in Vespa's internal repositories --> diff --git a/vespa-dependencies-enforcer/allowed-maven-dependencies.txt b/vespa-dependencies-enforcer/allowed-maven-dependencies.txt index 05b39902d5b..17d95a138a5 100644 --- a/vespa-dependencies-enforcer/allowed-maven-dependencies.txt +++ b/vespa-dependencies-enforcer/allowed-maven-dependencies.txt @@ -97,9 +97,9 @@ org.apache.felix:org.apache.felix.log:1.0.1 org.apache.httpcomponents:httpclient:4.5.14 org.apache.httpcomponents:httpcore:4.4.16 org.apache.httpcomponents:httpmime:4.5.14 -org.apache.httpcomponents.client5:httpclient5:5.2.1 -org.apache.httpcomponents.core5:httpcore5:5.2.1 -org.apache.httpcomponents.core5:httpcore5-h2:5.2.1 +org.apache.httpcomponents.client5:httpclient5:5.1.4 +org.apache.httpcomponents.core5:httpcore5:5.1.5 +org.apache.httpcomponents.core5:httpcore5-h2:5.1.5 org.apache.maven:maven-archiver:3.6.0 org.apache.maven:maven-artifact:3.8.6 org.apache.maven:maven-artifact-manager:2.2.1 diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java index 8b0509dc788..593d93ffe20 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/ApacheCluster.java @@ -5,11 +5,9 @@ import ai.vespa.feed.client.FeedClientBuilder.Compression; import ai.vespa.feed.client.HttpResponse; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; -import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; -import org.apache.hc.client5.http.impl.async.MinimalH2AsyncClient; import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; import org.apache.hc.core5.concurrent.FutureCallback; import org.apache.hc.core5.http.ContentType; @@ -60,10 +58,9 @@ class ApacheCluster implements Cluster { private final ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor(t -> new Thread(t, "request-timeout-thread")); ApacheCluster(FeedClientBuilderImpl builder) throws IOException { - ConnectionConfig connectionConfig = createConnectionConfig(); for (int i = 0; i < builder.connectionsPerEndpoint; i++) for (URI endpoint : builder.endpoints) - endpoints.add(new Endpoint(createHttpClient(builder, connectionConfig), endpoint)); + endpoints.add(new Endpoint(createHttpClient(builder), endpoint)); this.requestConfig = createRequestConfig(builder); this.compression = builder.compression; } @@ -162,8 +159,7 @@ class ApacheCluster implements Cluster { } - @SuppressWarnings("deprecation") - private static CloseableHttpAsyncClient createHttpClient(FeedClientBuilderImpl builder, ConnectionConfig connectionConfig) throws IOException { + private static CloseableHttpAsyncClient createHttpClient(FeedClientBuilderImpl builder) throws IOException { SSLContext sslContext = builder.constructSslContext(); String[] allowedCiphers = excludeH2Blacklisted(excludeWeak(sslContext.getSupportedSSLParameters().getCipherSuites())); if (allowedCiphers.length == 0) @@ -176,20 +172,18 @@ class ApacheCluster implements Cluster { if (builder.hostnameVerifier != null) tlsStrategyBuilder.setHostnameVerifier(builder.hostnameVerifier); - MinimalH2AsyncClient client = HttpAsyncClients.createHttp2Minimal(H2Config.custom() + return HttpAsyncClients.createHttp2Minimal(H2Config.custom() .setMaxConcurrentStreams(builder.maxStreamsPerConnection) .setCompressionEnabled(true) .setPushEnabled(false) .setInitialWindowSize(Integer.MAX_VALUE) .build(), IOReactorConfig.custom() - .setIoThreadCount(2) - .setTcpNoDelay(true) - .setSoTimeout(Timeout.ofSeconds(10)) - .build(), + .setIoThreadCount(2) + .setTcpNoDelay(true) + .setSoTimeout(Timeout.ofSeconds(10)) + .build(), tlsStrategyBuilder.build()); - client.setConnectionConfigResolver(host -> connectionConfig); - return client; } private static int portOf(URI url) { @@ -197,19 +191,12 @@ class ApacheCluster implements Cluster { : url.getPort(); } - private static ConnectionConfig createConnectionConfig() { - return ConnectionConfig.custom() - .setConnectTimeout(Timeout.ofSeconds(10)).build(); - } - - @SuppressWarnings("deprecation") private static RequestConfig createRequestConfig(FeedClientBuilderImpl b) { RequestConfig.Builder builder = RequestConfig.custom() + .setConnectTimeout(Timeout.ofSeconds(10)) .setConnectionRequestTimeout(Timeout.DISABLED) .setResponseTimeout(Timeout.ofSeconds(190)); - if (b.proxy != null) { - builder.setProxy(new HttpHost(b.proxy.getScheme(), b.proxy.getHost(), b.proxy.getPort())); - } + if (b.proxy != null) builder.setProxy(new HttpHost(b.proxy.getScheme(), b.proxy.getHost(), b.proxy.getPort())); return builder.build(); } diff --git a/vespaclient-java/src/main/java/com/yahoo/vespa/filedistribution/status/FileDistributionStatusClient.java b/vespaclient-java/src/main/java/com/yahoo/vespa/filedistribution/status/FileDistributionStatusClient.java index bb532589750..a9bbfafeaf0 100644 --- a/vespaclient-java/src/main/java/com/yahoo/vespa/filedistribution/status/FileDistributionStatusClient.java +++ b/vespaclient-java/src/main/java/com/yahoo/vespa/filedistribution/status/FileDistributionStatusClient.java @@ -71,17 +71,18 @@ public class FileDistributionStatusClient { System.out.println(parseAndGenerateOutput(json)); } - @SuppressWarnings("deprecation") private String doHttpRequest() { Timeout timeoutInMillis = Timeout.ofMilliseconds((long) (timeout * 1000)); RequestConfig config = custom() + .setConnectTimeout(timeoutInMillis) .setConnectionRequestTimeout(timeoutInMillis) .setResponseTimeout(timeoutInMillis) .build(); - try (CloseableHttpClient httpClient = VespaHttpClientBuilder.custom().connectTimeout(timeoutInMillis).buildClient()) { - URI statusUri = createStatusApiUri(); - if (debug) - System.out.println("URI:" + statusUri); + CloseableHttpClient httpClient = VespaHttpClientBuilder.create().build(); + URI statusUri = createStatusApiUri(); + if (debug) + System.out.println("URI:" + statusUri); + try { HttpGet request = new HttpGet(statusUri); request.addHeader("Connection", "Close"); request.setConfig(config); @@ -94,7 +95,7 @@ public class FileDistributionStatusClient { return content; } else { throw new RuntimeException("Failed to get status for request " + statusUri + ": " + - response.getCode() + ": " + content); + response.getCode() + ": " + content); } } catch (IOException | ParseException e) { throw new RuntimeException(e); @@ -110,12 +111,16 @@ public class FileDistributionStatusClient { throw new RuntimeException(e); } String status = jsonNode.get("status").asText(); - return switch (status) { - case statusUnknown -> "File distribution status unknown: " + jsonNode.get("message").asText(); - case statusInProgress -> "File distribution in progress:\n" + inProgressOutput(jsonNode.get("hosts")); - case statusFinished -> "File distribution finished"; - default -> throw new RuntimeException("Unknown status " + status); - }; + switch (status) { + case statusUnknown: + return "File distribution status unknown: " + jsonNode.get("message").asText(); + case statusInProgress: + return "File distribution in progress:\n" + inProgressOutput(jsonNode.get("hosts")); + case statusFinished: + return "File distribution finished"; + default: + throw new RuntimeException("Unknown status " + status); + } } private URI createStatusApiUri() { @@ -153,7 +158,7 @@ public class FileDistributionStatusClient { finished++; } } - sb.append(" (").append(finished).append(" of ").append(fileReferencesArray.size()).append(" finished)"); + sb.append(" (" + finished + " of " + fileReferencesArray.size() + " finished)"); break; case statusFinished: break; // Nothing to add |