Skip to content

Commit

Permalink
Fix compiler warnings and deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
michel-kraemer committed Mar 12, 2023
1 parent 8636307 commit 86a15f1
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 85 deletions.
134 changes: 69 additions & 65 deletions src/main/java/de/undercouch/gradle/tasks/download/DownloadAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.auth.BasicScheme;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.utils.DateUtils;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
import org.apache.hc.core5.util.Timeout;
import org.gradle.api.Action;
import org.gradle.api.JavaVersion;
Expand All @@ -50,7 +51,6 @@
import javax.annotation.Nullable;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
Expand All @@ -62,11 +62,12 @@
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -377,25 +378,26 @@ private void executeFileProtocol(URL src, long timestamp, File destFile,
private void executeHttpProtocol(URL src, HttpClientFactory clientFactory,
long timestamp, File destFile, ProgressLoggerWrapper progressLogger)
throws IOException {
//create HTTP host from URL
// create HTTP host from URL
HttpHost httpHost = new HttpHost(src.getProtocol(), src.getHost(), src.getPort());

//create HTTP client
// create HTTP client
CloseableHttpClient client = clientFactory.createHttpClient(
httpHost, acceptAnyCertificate, retries, headers, logger, quiet);
httpHost, acceptAnyCertificate, retries, connectTimeoutMs,
headers, logger, quiet);

//open URL connection
// get cached ETag if there is any
String etag = null;
if (onlyIfModified && useETag.enabled && destFile.exists()) {
etag = getCachedETag(httpHost, src.getFile());
if (!useETag.useWeakETags && isWeakETag(etag)) {
etag = null;
}
}
CloseableHttpResponse response = openConnection(httpHost, src.getFile(),
timestamp, etag, client);
try {
//check if file on server was modified

// open URL connection
openConnection(httpHost, src.getFile(), timestamp, etag, client, response -> {
// check if file on server was modified
long lastModified = parseLastModified(response);
int code = response.getCode();
if (code == HttpStatus.SC_NOT_MODIFIED ||
Expand All @@ -404,25 +406,25 @@ private void executeHttpProtocol(URL src, HttpClientFactory clientFactory,
logger.info("Not modified. Skipping '" + src + "'");
}
upToDate.incrementAndGet();
return;
return null;
}
//perform the download

// perform the download
performDownload(response, destFile, progressLogger);
} finally {
response.close();
}

//set last-modified time of destination file
long newTimestamp = parseLastModified(response);
if (onlyIfModified && newTimestamp > 0) {
destFile.setLastModified(newTimestamp);
}

//store ETag
if (onlyIfModified && useETag.enabled) {
storeETag(httpHost, src.getFile(), response);
}
// set last-modified time of destination file
long newTimestamp = parseLastModified(response);
if (onlyIfModified && newTimestamp > 0) {
destFile.setLastModified(newTimestamp);
}

// store ETag
if (onlyIfModified && useETag.enabled) {
storeETag(httpHost, src.getFile(), response);
}

return null;
});
}

/**
Expand All @@ -432,7 +434,7 @@ private void executeHttpProtocol(URL src, HttpClientFactory clientFactory,
* @param progressLogger progress logger
* @throws IOException if the response could not be downloaded
*/
private void performDownload(CloseableHttpResponse response, File destFile,
private void performDownload(ClassicHttpResponse response, File destFile,
ProgressLoggerWrapper progressLogger) throws IOException {
HttpEntity entity = response.getEntity();
if (entity == null) {
Expand Down Expand Up @@ -466,7 +468,7 @@ private void moveFile(File src, File dest,

// renameTo() failed. Try to copy the file and delete it afterwards.
// see issue #146
try (InputStream is = new FileInputStream(src)) {
try (InputStream is = Files.newInputStream(src.toPath())) {
stream(is, dest, progressLogger);
}
if (!src.delete()) {
Expand Down Expand Up @@ -778,11 +780,12 @@ private File makeDestFile(URL src, boolean multipleSources) {
* @param timestamp the timestamp of the destination file, in milliseconds
* @param etag the cached ETag for the requested host and file
* @param client the HTTP client to use to perform the request
* @return the URLConnection
* @param responseHandler a callback that handles the HTTP response
* @throws IOException if the connection could not be opened
*/
private CloseableHttpResponse openConnection(HttpHost httpHost, String file,
long timestamp, String etag, CloseableHttpClient client) throws IOException {
private <T> void openConnection(HttpHost httpHost, String file,
long timestamp, String etag, CloseableHttpClient client,
HttpClientResponseHandler<T> responseHandler) throws IOException {
// configure authentication
HttpClientContext context = null;
if (username != null && password != null) {
Expand All @@ -791,19 +794,18 @@ private CloseableHttpResponse openConnection(HttpHost httpHost, String file,
addAuthentication(httpHost, c, context);
}

//create request
//c reate request
HttpGet get = new HttpGet(file);

//configure timeouts
// configure timeouts
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(Timeout.ofMilliseconds(connectTimeoutMs))
.setConnectionRequestTimeout(Timeout.ofMilliseconds(connectTimeoutMs))
.setResponseTimeout(Timeout.ofMilliseconds(readTimeoutMs))
.setContentCompressionEnabled(compress)
.build();
get.setConfig(config);

//add authentication information for proxy
// add authentication information for proxy
String scheme = httpHost.getSchemeName();
String proxyHost = System.getProperty(scheme + ".proxyHost");
String proxyPort = System.getProperty(scheme + ".proxyPort");
Expand All @@ -821,48 +823,50 @@ private CloseableHttpResponse openConnection(HttpHost httpHost, String file,
addAuthentication(proxy, credentials, context);
}

//set If-Modified-Since header
// set If-Modified-Since header
if (timestamp > 0) {
get.setHeader("If-Modified-Since", DateUtils.formatDate(new Date(timestamp)));
get.setHeader("If-Modified-Since", DateUtils.formatStandardDate(
Instant.ofEpochMilli(timestamp)));
}

//set If-None-Match header
// set If-None-Match header
if (etag != null) {
get.setHeader("If-None-Match", etag);
}

//set headers
// set headers
if (headers != null) {
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
get.addHeader(headerEntry.getKey(), headerEntry.getValue());
}
}

//execute request
CloseableHttpResponse response = client.execute(httpHost, get, context);

//handle response
int code = response.getCode();
if ((code < 200 || code > 299) && code != HttpStatus.SC_NOT_MODIFIED) {
String url = httpHost + file;
String message = "HTTP status code: " + code + ", URL: " + url;
if (code == HttpStatus.SC_UNAUTHORIZED && !response.containsHeader(HttpHeaders.WWW_AUTHENTICATE)) {
message += ". Missing " + HttpHeaders.WWW_AUTHENTICATE + " header in response; use the " +
"preemptiveAuth flag to send credentials in first request";
}
String phrase = response.getReasonPhrase();
if (phrase == null || phrase.isEmpty()) {
phrase = message;
} else {
phrase += " (" + message + ")";
// execute request
client.execute(httpHost, get, context, response -> {
// handle response
int code = response.getCode();
if ((code < 200 || code > 299) && code != HttpStatus.SC_NOT_MODIFIED) {
String url = httpHost + file;
String message = "HTTP status code: " + code + ", URL: " + url;
if (code == HttpStatus.SC_UNAUTHORIZED &&
!response.containsHeader(HttpHeaders.WWW_AUTHENTICATE)) {
message += ". Missing " + HttpHeaders.WWW_AUTHENTICATE +
" header in response; use the preemptiveAuth flag" +
" to send credentials in the first request.";
}
String phrase = response.getReasonPhrase();
if (phrase == null || phrase.isEmpty()) {
phrase = message;
} else {
phrase += " (" + message + ")";
}
throw new ClientProtocolException(phrase);
}
response.close();
throw new ClientProtocolException(phrase);
}

return response;

return responseHandler.handleResponse(response);
});
}

/**
* Add authentication information for the given host
* @param host the host
Expand Down Expand Up @@ -907,11 +911,11 @@ private long parseLastModified(HttpResponse response) {
if (value == null || value.isEmpty()) {
return 0;
}
Date date = DateUtils.parseDate(value);
Instant date = DateUtils.parseStandardDate(value);
if (date == null) {
return 0;
}
return date.getTime();
return date.toEpochMilli();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ public class CachingHttpClientFactory extends DefaultHttpClientFactory {

@Override
public CloseableHttpClient createHttpClient(HttpHost httpHost,
boolean acceptAnyCertificate, int retries, Map<String, String> headers,
Logger logger, boolean quiet) {
boolean acceptAnyCertificate, int retries, int connectTimeoutMs,
Map<String, String> headers, Logger logger, boolean quiet) {
CacheKey key = new CacheKey(httpHost, acceptAnyCertificate, retries);
CloseableHttpClient c = cachedClients.get(key);
if (c == null) {
c = super.createHttpClient(httpHost, acceptAnyCertificate, retries,
headers, logger, quiet);
connectTimeoutMs, headers, logger, quiet);
cachedClients.put(key, c);
}
return c;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public boolean equals(Object o) {
return false;
}
DefaultDownloadDetails that = (DefaultDownloadDetails)o;
return relativePath.equals(that.relativePath) && sourceURL.equals(that.sourceURL);
return relativePath.equals(that.relativePath) &&
sourceURL.toString().equals(that.sourceURL.toString());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@

package de.undercouch.gradle.tasks.download.internal;

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.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner;
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.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.HttpHost;
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 org.gradle.api.logging.Logger;

import javax.net.ssl.HostnameVerifier;
Expand All @@ -38,7 +40,7 @@

/**
* Default implementation of {@link HttpClientFactory}. Creates a new client
* every time {@link #createHttpClient(HttpHost, boolean, int, Map, Logger, boolean)}
* every time {@link #createHttpClient(HttpHost, boolean, int, int, Map, Logger, boolean)}
* is called. The caller is responsible for closing this client.
* @author Michel Kraemer
*/
Expand All @@ -52,11 +54,11 @@ public class DefaultHttpClientFactory implements HttpClientFactory {

@Override
public CloseableHttpClient createHttpClient(HttpHost httpHost,
boolean acceptAnyCertificate, final int retries,
boolean acceptAnyCertificate, final int retries, int connectTimeoutMs,
Map<String, String> headers, Logger logger, boolean quiet) {
HttpClientBuilder builder = HttpClientBuilder.create();

//configure retries
// configure retries
if (retries == 0) {
builder.disableAutomaticRetries();
} else {
Expand All @@ -69,23 +71,30 @@ public CloseableHttpClient createHttpClient(HttpHost httpHost,
maxRetries, TimeValue.ofSeconds(0L), logger, quiet));
}

//configure proxy from system environment
// configure proxy from system environment
builder.setRoutePlanner(new SystemDefaultRoutePlanner(null));

//accept any certificate if necessary
// use pooling connection manager to support multiple threads
PoolingHttpClientConnectionManager cm;
if ("https".equals(httpHost.getSchemeName()) && acceptAnyCertificate) {
// accept any certificate if necessary
SSLConnectionSocketFactory icsf = getInsecureSSLSocketFactory();
Registry<ConnectionSocketFactory> registry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", icsf)
.register("http", PlainConnectionSocketFactory.INSTANCE)
.build();
// use pooling connection manager to support multiple threads
HttpClientConnectionManager cm =
new PoolingHttpClientConnectionManager(registry);
builder.setConnectionManager(cm);
cm = new PoolingHttpClientConnectionManager(registry);
} else {
cm = PoolingHttpClientConnectionManagerBuilder.create().build();
}

// configure connection timeout
cm.setDefaultConnectionConfig(ConnectionConfig.custom()
.setConnectTimeout(Timeout.ofMilliseconds(connectTimeoutMs))
.build());
builder.setConnectionManager(cm);

// add interceptor that strips the standard ports :80 and :443 from the
// Host header unless the host has been explicitly specified by the user
builder.addRequestInterceptorLast(new StripPortsFromHostInterceptor(headers));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@ public interface HttpClientFactory {
* errors should be ignored and any certificate (even an invalid one)
* should be accepted
* @param retries the number of retries to perform if an HTTP request fails
* @param connectTimeoutMs the maximum number of milliseconds to wait until
* a connection is established. A value of 0 (zero) means infinite timeout.
* A negative value is interpreted as undefined.
* @param headers the HTTP headers specified by the user
* @param logger the project's logger
* @param quiet {@code true} if the quiet flag is set
* @return the HTTP client
*/
CloseableHttpClient createHttpClient(HttpHost httpHost, boolean acceptAnyCertificate,
int retries, Map<String, String> headers, Logger logger, boolean quiet);
int retries, int connectTimeoutMs, Map<String, String> headers,
Logger logger, boolean quiet);
}
Loading

0 comments on commit 86a15f1

Please sign in to comment.