]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19579 Fix SSF-420 (#8573)
authorWojtek Wajerowicz <115081248+wojciech-wajerowicz-sonarsource@users.noreply.github.com>
Thu, 15 Jun 2023 05:32:29 +0000 (07:32 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 15 Jun 2023 09:41:52 +0000 (09:41 +0000)
sonar-core/build.gradle
sonar-core/src/it/java/org/sonar/core/util/DefaultHttpDownloaderIT.java
sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java
sonar-core/src/main/java/org/sonar/core/util/HttpsTrust.java [deleted file]
sonar-core/src/test/java/org/sonar/core/util/HttpsTrustTest.java [deleted file]

index 7c85982378f88191fab9db7c26f0110f6bdba39d..8f8abccb27a3953351024a1998490b0f885919c4 100644 (file)
@@ -11,6 +11,7 @@ dependencies {
   api 'ch.qos.logback:logback-core'
   api 'com.google.guava:guava'
   api 'com.google.protobuf:protobuf-java'
+  api 'com.squareup.okhttp3:okhttp'
   api 'commons-codec:commons-codec'
   api 'commons-io:commons-io'
   api 'commons-lang:commons-lang'
@@ -22,6 +23,7 @@ dependencies {
   api 'org.sonarsource.update-center:sonar-update-center-common'
   api 'org.springframework:spring-context'
   api project(':sonar-plugin-api-impl')
+  api project(':sonar-ws')
 
   compileOnlyApi 'com.google.code.findbugs:jsr305'
   compileOnlyApi 'com.google.code.gson:gson'
index c185bbbdc0d1b84a8acfab36b1ed496107bceb4f..63e0afc55203c14d05cda0233894534f81f352d2 100644 (file)
@@ -22,16 +22,13 @@ package org.sonar.core.util;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.PrintStream;
 import java.net.InetSocketAddress;
-import java.net.PasswordAuthentication;
-import java.net.Proxy;
-import java.net.ProxySelector;
 import java.net.SocketAddress;
 import java.net.SocketTimeoutException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
 import java.util.Properties;
 import java.util.zip.GZIPOutputStream;
 import org.hamcrest.BaseMatcher;
@@ -56,10 +53,7 @@ import org.sonar.api.utils.SonarException;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class DefaultHttpDownloaderIT {
@@ -67,7 +61,6 @@ public class DefaultHttpDownloaderIT {
   @Rule
   public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
-
   @Rule
   public TestRule safeguardTimeout = new DisableOnDebug(Timeout.seconds(60));
 
@@ -81,27 +74,28 @@ public class DefaultHttpDownloaderIT {
         try {
           if (req.getPath().getPath().contains("/redirect/")) {
             resp.setCode(303);
-            resp.setValue("Location", "/");
-          } else {
-            if (req.getPath().getPath().contains("/timeout/")) {
-              try {
-                Thread.sleep(500);
-              } catch (InterruptedException e) {
-                throw new IllegalStateException(e);
-              }
+            resp.setValue("Location", "/redirected");
+          } else if (req.getPath().getPath().contains("/timeout/")) {
+            try {
+              Thread.sleep(500);
+              writeDefaultResponse(req, resp);
+            } catch (InterruptedException e) {
+              throw new IllegalStateException(e);
             }
-            if (req.getPath().getPath().contains("/gzip/")) {
-              if (!"gzip".equals(req.getValue("Accept-Encoding"))) {
-                throw new IllegalStateException("Should accept gzip");
-              }
-              resp.setValue("Content-Encoding", "gzip");
-              GZIPOutputStream gzipOutputStream = new GZIPOutputStream(resp.getOutputStream());
-              gzipOutputStream.write("GZIP response".getBytes());
-              gzipOutputStream.close();
-            } else {
-              resp.getPrintStream().append("agent=" + req.getValues("User-Agent").get(0));
+          } else if (req.getPath().getPath().contains("/gzip/")) {
+            if (!"gzip".equals(req.getValue("Accept-Encoding"))) {
+              throw new IllegalStateException("Should accept gzip");
             }
+            resp.setValue("Content-Encoding", "gzip");
+            GZIPOutputStream gzipOutputStream = new GZIPOutputStream(resp.getOutputStream());
+            gzipOutputStream.write("GZIP response".getBytes());
+            gzipOutputStream.close();
+          } else if (req.getPath().getPath().contains("/redirected")) {
+            resp.getPrintStream().append("redirected");
+          } else {
+            writeDefaultResponse(req, resp);
           }
+
         } catch (IOException e) {
           throw new IllegalStateException(e);
         } finally {
@@ -117,6 +111,10 @@ public class DefaultHttpDownloaderIT {
     baseUrl = String.format("http://%s:%d", ((InetSocketAddress) address).getAddress().getHostAddress(), ((InetSocketAddress) address).getPort());
   }
 
+  private static PrintStream writeDefaultResponse(Request req, Response resp) throws IOException {
+    return resp.getPrintStream().append("agent=" + req.getValues("User-Agent").get(0));
+  }
+
   @AfterClass
   public static void stopServer() throws IOException {
     if (null != socketConnection) {
@@ -130,7 +128,7 @@ public class DefaultHttpDownloaderIT {
     String url = "http://10.255.255.1";
 
     assertThatThrownBy(() -> {
-      DefaultHttpDownloader downloader = new DefaultHttpDownloader(new MapSettings().asConfig(), 10, 10);
+      DefaultHttpDownloader downloader = new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig(), 10, 10);
       downloader.openStream(new URI(url));
     })
       .isInstanceOf(SonarException.class)
@@ -148,31 +146,32 @@ public class DefaultHttpDownloaderIT {
 
   @Test
   public void downloadBytes() throws URISyntaxException {
-    byte[] bytes = new DefaultHttpDownloader(new MapSettings().asConfig()).readBytes(new URI(baseUrl));
+    byte[] bytes = new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).readBytes(new URI(baseUrl));
     assertThat(bytes.length).isGreaterThan(10);
   }
 
   @Test
   public void readString() throws URISyntaxException {
-    String text = new DefaultHttpDownloader(new MapSettings().asConfig()).readString(new URI(baseUrl), StandardCharsets.UTF_8);
+    String text = new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).readString(new URI(baseUrl), StandardCharsets.UTF_8);
     assertThat(text.length()).isGreaterThan(10);
   }
 
   @Test
   public void readGzipString() throws URISyntaxException {
-    String text = new DefaultHttpDownloader(new MapSettings().asConfig()).readString(new URI(baseUrl + "/gzip/"), StandardCharsets.UTF_8);
+    String text = new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).readString(new URI(baseUrl + "/gzip/"), StandardCharsets.UTF_8);
     assertThat(text).isEqualTo("GZIP response");
   }
 
   @Test
   public void readStringWithDefaultTimeout() throws URISyntaxException {
-    String text = new DefaultHttpDownloader(new MapSettings().asConfig()).readString(new URI(baseUrl + "/timeout/"), StandardCharsets.UTF_8);
+    String text = new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).readString(new URI(baseUrl + "/timeout/"), StandardCharsets.UTF_8);
     assertThat(text.length()).isGreaterThan(10);
   }
 
   @Test
   public void readStringWithTimeout() throws URISyntaxException {
-    assertThatThrownBy(() -> new DefaultHttpDownloader(new MapSettings().asConfig(), 50).readString(new URI(baseUrl + "/timeout/"), StandardCharsets.UTF_8))
+    assertThatThrownBy(
+      () -> new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig(), null, 50).readString(new URI(baseUrl + "/timeout/"), StandardCharsets.UTF_8))
       .isEqualToComparingFieldByField(new BaseMatcher<Exception>() {
         @Override
         public boolean matches(Object ex) {
@@ -190,7 +189,7 @@ public class DefaultHttpDownloaderIT {
     File toDir = temporaryFolder.newFolder();
     File toFile = new File(toDir, "downloadToFile.txt");
 
-    new DefaultHttpDownloader(new MapSettings().asConfig()).download(new URI(baseUrl), toFile);
+    new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).download(new URI(baseUrl), toFile);
     assertThat(toFile).exists();
     assertThat(toFile.length()).isGreaterThan(10L);
   }
@@ -201,8 +200,7 @@ public class DefaultHttpDownloaderIT {
     File toFile = new File(toDir, "downloadToFile.txt");
 
     try {
-      int port = new InetSocketAddress("localhost", 0).getPort();
-      new DefaultHttpDownloader(new MapSettings().asConfig()).download(new URI("http://localhost:" + port), toFile);
+      new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).download(new URI("http://localhost:1"), toFile);
     } catch (SonarException e) {
       assertThat(toFile).doesNotExist();
     }
@@ -236,68 +234,21 @@ public class DefaultHttpDownloaderIT {
     assertThat(props.getProperty("agent")).isEqualTo("SonarQube 2.2 #");
   }
 
-  @Test
-  public void userAgent_is_static_value_when_server_is_not_provided() throws URISyntaxException, IOException {
-    InputStream stream = new DefaultHttpDownloader(new MapSettings().asConfig()).openStream(new URI(baseUrl));
-    Properties props = new Properties();
-    props.load(stream);
-    stream.close();
-
-    assertThat(props.getProperty("agent")).isEqualTo("SonarQube");
-  }
-
   @Test
   public void followRedirect() throws URISyntaxException {
-    String content = new DefaultHttpDownloader(new MapSettings().asConfig()).readString(new URI(baseUrl + "/redirect/"), StandardCharsets.UTF_8);
-    assertThat(content).contains("agent");
-  }
-
-  @Test
-  public void shouldGetDirectProxySynthesis() throws URISyntaxException {
-    ProxySelector proxySelector = mock(ProxySelector.class);
-    when(proxySelector.select(any(URI.class))).thenReturn(Arrays.asList(Proxy.NO_PROXY));
-    assertThat(DefaultHttpDownloader.BaseHttpDownloader.getProxySynthesis(new URI("http://an_url"), proxySelector)).isEqualTo("no proxy");
-  }
-
-  @Test
-  public void shouldGetProxySynthesis() throws URISyntaxException {
-    ProxySelector proxySelector = mock(ProxySelector.class);
-    when(proxySelector.select(any(URI.class))).thenReturn(Arrays.asList(new FakeProxy()));
-    assertThat(DefaultHttpDownloader.BaseHttpDownloader.getProxySynthesis(new URI("http://an_url"), proxySelector)).isEqualTo("HTTP proxy: /123.45.67.89:4040");
+    String content = new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).readString(new URI(baseUrl + "/redirect/"), StandardCharsets.UTF_8);
+    assertThat(content).isEqualTo("redirected");
   }
 
   @Test
   public void supported_schemes() {
-    assertThat(new DefaultHttpDownloader(new MapSettings().asConfig()).getSupportedSchemes()).contains("http");
+    assertThat(new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).getSupportedSchemes()).contains("http");
   }
 
   @Test
   public void uri_description() throws URISyntaxException {
-    String description = new DefaultHttpDownloader(new MapSettings().asConfig()).description(new URI("http://sonarsource.org"));
-    assertThat(description).matches("http://sonarsource.org \\(.*\\)");
-  }
-
-  @Test
-  public void configure_http_proxy_credentials() {
-    DefaultHttpDownloader.AuthenticatorFacade system = mock(DefaultHttpDownloader.AuthenticatorFacade.class);
-    MapSettings settings = new MapSettings();
-    settings.setProperty("https.proxyHost", "1.2.3.4");
-    settings.setProperty("http.proxyUser", "the_login");
-    settings.setProperty("http.proxyPassword", "the_passwd");
-
-    new DefaultHttpDownloader.BaseHttpDownloader(system, settings.asConfig(), null);
-
-    verify(system).setDefaultAuthenticator(argThat(authenticator -> {
-      DefaultHttpDownloader.ProxyAuthenticator a = (DefaultHttpDownloader.ProxyAuthenticator) authenticator;
-      PasswordAuthentication authentication = a.getPasswordAuthentication();
-      return authentication.getUserName().equals("the_login") &&
-        new String(authentication.getPassword()).equals("the_passwd");
-    }));
+    String description = new DefaultHttpDownloader(mock(Server.class), new MapSettings().asConfig()).description(new URI("http://sonarsource.org"));
+    assertThat(description).isEqualTo("http://sonarsource.org");
   }
 
-  private static class FakeProxy extends Proxy {
-    FakeProxy() {
-      super(Type.HTTP, new InetSocketAddress("123.45.67.89", 4040));
-    }
-  }
 }
index a61aeb5dc5a5db3f7f06b892bbbf71fc102090ef..8db9479e61da5e45e896c52f2927004dc32d99e6 100644 (file)
  */
 package org.sonar.core.util;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
 import com.google.common.io.ByteStreams;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.Authenticator;
-import java.net.HttpURLConnection;
-import java.net.PasswordAuthentication;
-import java.net.Proxy;
-import java.net.ProxySelector;
 import java.net.URI;
 import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
 import java.util.Optional;
-import java.util.zip.GZIPInputStream;
 import javax.annotation.Nullable;
 import javax.inject.Inject;
-import org.apache.commons.codec.binary.Base64;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
 import org.apache.commons.io.IOUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.HttpDownloader;
 import org.sonar.api.utils.SonarException;
+import org.sonarqube.ws.client.OkHttpClientBuilder;
 
 import static org.apache.commons.io.FileUtils.copyInputStreamToFile;
 import static org.sonar.core.util.FileUtils.deleteQuietly;
@@ -60,43 +49,44 @@ import static org.sonar.core.util.FileUtils.deleteQuietly;
  */
 public class DefaultHttpDownloader extends HttpDownloader {
 
-  private static final Logger LOG = LoggerFactory.getLogger(DefaultHttpDownloader.class);
-  private final BaseHttpDownloader downloader;
-  private final Integer readTimeout;
-  private final Integer connectTimeout;
+  private final OkHttpClient client;
 
   @Inject
   public DefaultHttpDownloader(Server server, Configuration config) {
-    this(server, config, null);
-  }
-
-  public DefaultHttpDownloader(Server server, Configuration config, @Nullable Integer readTimeout) {
-    this(server, config, null, readTimeout);
+    this(server, config, null, null);
   }
 
   public DefaultHttpDownloader(Server server, Configuration config, @Nullable Integer connectTimeout, @Nullable Integer readTimeout) {
-    this.readTimeout = readTimeout;
-    this.connectTimeout = connectTimeout;
-    downloader = new BaseHttpDownloader(new AuthenticatorFacade(), config, server.getVersion());
-  }
-
-  public DefaultHttpDownloader(Configuration config) {
-    this(config, null);
+    client = buildHttpClient(server, config, connectTimeout, readTimeout);
   }
 
-  public DefaultHttpDownloader(Configuration config, @Nullable Integer readTimeout) {
-    this(config, null, readTimeout);
+  private static OkHttpClient buildHttpClient(Server server, Configuration config, @Nullable Integer connectTimeout,
+    @Nullable Integer readTimeout) {
+    OkHttpClientBuilder clientBuilder = new OkHttpClientBuilder()
+      .setFollowRedirects(true)
+      .setUserAgent(getUserAgent(server, config));
+    if (connectTimeout != null) {
+      clientBuilder
+        .setConnectTimeoutMs(connectTimeout);
+    }
+    if (readTimeout != null) {
+      clientBuilder
+        .setReadTimeoutMs(readTimeout);
+    }
+    return clientBuilder.build();
   }
 
-  public DefaultHttpDownloader(Configuration config, @Nullable Integer connectTimeout, @Nullable Integer readTimeout) {
-    this.readTimeout = readTimeout;
-    this.connectTimeout = connectTimeout;
-    downloader = new BaseHttpDownloader(new AuthenticatorFacade(), config, null);
+  private static String getUserAgent(Server server, Configuration config) {
+    Optional<String> serverId = config.get(CoreProperties.SERVER_ID);
+    if (serverId.isEmpty()) {
+      return String.format("SonarQube %s #", server.getVersion());
+    }
+    return String.format("SonarQube %s # %s", server.getVersion(), serverId.get());
   }
 
   @Override
   protected String description(URI uri) {
-    return String.format("%s (%s)", uri.toString(), getProxySynthesis(uri));
+    return uri.toString();
   }
 
   @Override
@@ -111,8 +101,8 @@ public class DefaultHttpDownloader extends HttpDownloader {
 
   @Override
   protected String readString(URI uri, Charset charset) {
-    try {
-      return IOUtils.toString(downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout).getInput(), charset);
+    try (Response response = executeCall(uri)) {
+      return IOUtils.toString(response.body().byteStream(), charset);
     } catch (IOException e) {
       throw failToDownload(uri, e);
     }
@@ -125,21 +115,18 @@ public class DefaultHttpDownloader extends HttpDownloader {
 
   @Override
   public byte[] download(URI uri) {
-    try {
-      return ByteStreams.toByteArray(downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout).getInput());
+    try (Response response = executeCall(uri)) {
+      return ByteStreams.toByteArray(response.body().byteStream());
     } catch (IOException e) {
       throw failToDownload(uri, e);
     }
   }
 
-  public String getProxySynthesis(URI uri) {
-    return BaseHttpDownloader.getProxySynthesis(uri);
-  }
-
   @Override
   public InputStream openStream(URI uri) {
     try {
-      return downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout).getInput();
+      Response response = executeCall(uri);
+      return response.body().byteStream();
     } catch (IOException e) {
       throw failToDownload(uri, e);
     }
@@ -147,176 +134,21 @@ public class DefaultHttpDownloader extends HttpDownloader {
 
   @Override
   public void download(URI uri, File toFile) {
-    try {
-      copyInputStreamToFile(downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout).getInput(), toFile);
+    try (Response response = executeCall(uri)) {
+      copyInputStreamToFile(response.body().byteStream(), toFile);
     } catch (IOException e) {
       deleteQuietly(toFile);
       throw failToDownload(uri, e);
     }
   }
 
-  private SonarException failToDownload(URI uri, IOException e) {
-    throw new SonarException(String.format("Fail to download: %s (%s)", uri, getProxySynthesis(uri)), e);
-  }
-
-  /**
-   * Facade to allow unit tests to verify calls to {@link Authenticator#setDefault(Authenticator)}.
-   */
-  static class AuthenticatorFacade {
-    void setDefaultAuthenticator(Authenticator authenticator) {
-      Authenticator.setDefault(authenticator);
-    }
+  private Response executeCall(URI uri) throws IOException {
+    Request request = new Request.Builder().url(uri.toURL()).get().build();
+    return client.newCall(request).execute();
   }
 
-  static class BaseHttpDownloader {
-
-    private static final String GET = "GET";
-    private static final String HTTP_PROXY_USER = "http.proxyUser";
-    private static final String HTTP_PROXY_PASSWORD = "http.proxyPassword";
-
-    private String userAgent;
-
-    BaseHttpDownloader(AuthenticatorFacade system, Configuration config, @Nullable String userAgent) {
-      initProxy(system, config);
-      initUserAgent(userAgent, config);
-    }
-
-    private static void initProxy(AuthenticatorFacade system, Configuration config) {
-      // register credentials
-      Optional<String> login = config.get(HTTP_PROXY_USER);
-      if (login.isPresent()) {
-        system.setDefaultAuthenticator(new ProxyAuthenticator(login.get(), config.get(HTTP_PROXY_PASSWORD).orElse(null)));
-      }
-    }
-
-    private void initUserAgent(@Nullable String sonarVersion, Configuration settings) {
-      Optional<String> serverId = settings.get(CoreProperties.SERVER_ID);
-      userAgent = sonarVersion == null ? "SonarQube" : String.format("SonarQube %s # %s", sonarVersion, serverId.orElse(""));
-      System.setProperty("http.agent", userAgent);
-    }
-
-    private static String getProxySynthesis(URI uri) {
-      return getProxySynthesis(uri, ProxySelector.getDefault());
-    }
-
-    @VisibleForTesting
-    static String getProxySynthesis(URI uri, ProxySelector proxySelector) {
-      List<Proxy> proxies = proxySelector.select(uri);
-      if (proxies.size() == 1 && proxies.get(0).type().equals(Proxy.Type.DIRECT)) {
-        return "no proxy";
-      }
-
-      List<String> descriptions = Lists.newArrayList();
-      for (Proxy proxy : proxies) {
-        if (proxy.type() != Proxy.Type.DIRECT) {
-          descriptions.add(proxy.type() + " proxy: " + proxy.address());
-        }
-      }
-
-      return Joiner.on(", ").join(descriptions);
-    }
-
-    public HttpInputSupplier newInputSupplier(URI uri, @Nullable Integer connectTimeoutMillis, @Nullable Integer readTimeoutMillis) {
-      return newInputSupplier(uri, GET, connectTimeoutMillis, readTimeoutMillis);
-    }
-
-    public HttpInputSupplier newInputSupplier(URI uri, String requestMethod, @Nullable Integer connectTimeoutMillis, @Nullable Integer readTimeoutMillis) {
-      return newInputSupplier(uri, requestMethod, null, null, connectTimeoutMillis, readTimeoutMillis);
-    }
-
-    public HttpInputSupplier newInputSupplier(URI uri, String requestMethod, String login, String password, @Nullable Integer connectTimeoutMillis,
-      @Nullable Integer readTimeoutMillis) {
-      int read = readTimeoutMillis != null ? readTimeoutMillis : DEFAULT_READ_TIMEOUT_IN_MILLISECONDS;
-      int connect = connectTimeoutMillis != null ? connectTimeoutMillis : DEFAULT_CONNECT_TIMEOUT_IN_MILLISECONDS;
-      return new HttpInputSupplier(uri, requestMethod, userAgent, login, password, connect, read);
-    }
-
-    private static class HttpInputSupplier {
-      private final String login;
-      private final String password;
-      private final URI uri;
-      private final String userAgent;
-      private final int connectTimeoutMillis;
-      private final int readTimeoutMillis;
-      private final String requestMethod;
-
-      HttpInputSupplier(URI uri, String requestMethod, String userAgent, String login, String password, int connectTimeoutMillis, int readTimeoutMillis) {
-        this.uri = uri;
-        this.requestMethod = requestMethod;
-        this.userAgent = userAgent;
-        this.login = login;
-        this.password = password;
-        this.readTimeoutMillis = readTimeoutMillis;
-        this.connectTimeoutMillis = connectTimeoutMillis;
-      }
-
-      /**
-       * @throws IOException any I/O error, not limited to the network connection
-       * @throws HttpException if HTTP response code > 400
-       */
-      public InputStream getInput() throws IOException {
-        LOG.debug("Download: {}} ( {} )", uri, getProxySynthesis(uri, ProxySelector.getDefault()));
-        HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
-        connection.setRequestMethod(requestMethod);
-        HttpsTrust.INSTANCE.trust(connection);
-
-        // allow both GZip and Deflate (ZLib) encodings
-        connection.setRequestProperty("Accept-Encoding", "gzip");
-        if (!Strings.isNullOrEmpty(login)) {
-          String encoded = Base64.encodeBase64String((login + ":" + password).getBytes(StandardCharsets.UTF_8));
-          connection.setRequestProperty("Authorization", "Basic " + encoded);
-        }
-        connection.setConnectTimeout(connectTimeoutMillis);
-        connection.setReadTimeout(readTimeoutMillis);
-        connection.setUseCaches(true);
-        connection.setInstanceFollowRedirects(true);
-        connection.setRequestProperty("User-Agent", userAgent);
-
-        // establish connection, get response headers
-        connection.connect();
-
-        // obtain the encoding returned by the server
-        String encoding = connection.getContentEncoding();
-
-        int responseCode = connection.getResponseCode();
-        if (responseCode >= 400) {
-          InputStream errorResponse = null;
-          try {
-            errorResponse = connection.getErrorStream();
-            if (errorResponse != null) {
-              String errorResponseContent = IOUtils.toString(errorResponse);
-              throw new HttpException(uri, responseCode, errorResponseContent);
-            }
-            throw new HttpException(uri, responseCode);
-
-          } finally {
-            IOUtils.closeQuietly(errorResponse);
-          }
-        }
-
-        InputStream resultingInputStream;
-        // create the appropriate stream wrapper based on the encoding type
-        if ("gzip".equalsIgnoreCase(encoding)) {
-          resultingInputStream = new GZIPInputStream(connection.getInputStream());
-        } else {
-          resultingInputStream = connection.getInputStream();
-        }
-        return resultingInputStream;
-      }
-    }
-  }
-
-  static class ProxyAuthenticator extends Authenticator {
-    private final PasswordAuthentication auth;
-
-    ProxyAuthenticator(String user, @Nullable String password) {
-      auth = new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
-    }
-
-    @Override
-    protected PasswordAuthentication getPasswordAuthentication() {
-      return auth;
-    }
+  private static SonarException failToDownload(URI uri, IOException e) {
+    throw new SonarException(String.format("Fail to download: %s", uri), e);
   }
 
 }
diff --git a/sonar-core/src/main/java/org/sonar/core/util/HttpsTrust.java b/sonar-core/src/main/java/org/sonar/core/util/HttpsTrust.java
deleted file mode 100644 (file)
index 2fb2b23..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.core.util;
-
-import java.net.HttpURLConnection;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * @since 4.0
- */
-class HttpsTrust {
-
-  static final HttpsTrust INSTANCE = new HttpsTrust(new Ssl());
-
-  static class Ssl {
-    SSLSocketFactory newFactory(TrustManager... managers) throws NoSuchAlgorithmException, KeyManagementException {
-      SSLContext context = SSLContext.getInstance("TLS");
-      context.init(null, managers, new SecureRandom());
-      return context.getSocketFactory();
-    }
-  }
-
-  private final SSLSocketFactory socketFactory;
-  private final HostnameVerifier hostnameVerifier;
-
-  HttpsTrust(Ssl context) {
-    this.socketFactory = createSocketFactory(context);
-    this.hostnameVerifier = createHostnameVerifier();
-  }
-
-  void trust(HttpURLConnection connection) {
-    if (connection instanceof HttpsURLConnection) {
-      HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
-      httpsConnection.setSSLSocketFactory(socketFactory);
-      httpsConnection.setHostnameVerifier(hostnameVerifier);
-    }
-  }
-
-  /**
-   * Trust all certificates
-   */
-  private static SSLSocketFactory createSocketFactory(Ssl context) {
-    try {
-      return context.newFactory(new AlwaysTrustManager());
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to build SSL factory", e);
-    }
-  }
-
-  /**
-   * Trust all hosts
-   */
-  private static HostnameVerifier createHostnameVerifier() {
-    return (hostname, session) -> true;
-  }
-
-  static class AlwaysTrustManager implements X509TrustManager {
-    @Override
-    public X509Certificate[] getAcceptedIssuers() {
-      return new X509Certificate[0];
-    }
-
-    @Override
-    public void checkClientTrusted(X509Certificate[] chain, String authType) {
-      // Do not check
-    }
-
-    @Override
-    public void checkServerTrusted(X509Certificate[] chain, String authType) {
-      // Do not check
-    }
-  }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/HttpsTrustTest.java b/sonar-core/src/test/java/org/sonar/core/util/HttpsTrustTest.java
deleted file mode 100644 (file)
index 85e1f57..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.core.util;
-
-import java.io.IOException;
-import java.net.URL;
-import java.security.KeyManagementException;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.TrustManager;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class HttpsTrustTest {
-  @Test
-  public void trustAllHosts() throws Exception {
-    HttpsURLConnection connection = newHttpsConnection();
-    HttpsTrust.INSTANCE.trust(connection);
-
-    assertThat(connection.getHostnameVerifier()).isNotNull();
-    assertThat(connection.getHostnameVerifier().verify("foo", null)).isTrue();
-  }
-
-  @Test
-  public void singleHostnameVerifier() throws Exception {
-    HttpsURLConnection connection1 = newHttpsConnection();
-    HttpsTrust.INSTANCE.trust(connection1);
-    HttpsURLConnection connection2 = newHttpsConnection();
-    HttpsTrust.INSTANCE.trust(connection2);
-
-    assertThat(connection1.getHostnameVerifier()).isSameAs(connection2.getHostnameVerifier());
-  }
-
-  @Test
-  public void trustAllCerts() throws Exception {
-    HttpsURLConnection connection1 = newHttpsConnection();
-    HttpsTrust.INSTANCE.trust(connection1);
-
-    assertThat(connection1.getSSLSocketFactory()).isNotNull();
-    assertThat(connection1.getSSLSocketFactory().getDefaultCipherSuites()).isNotEmpty();
-  }
-
-  @Test
-  public void singleSslFactory() throws Exception {
-    HttpsURLConnection connection1 = newHttpsConnection();
-    HttpsTrust.INSTANCE.trust(connection1);
-    HttpsURLConnection connection2 = newHttpsConnection();
-    HttpsTrust.INSTANCE.trust(connection2);
-
-    assertThat(connection1.getSSLSocketFactory()).isSameAs(connection2.getSSLSocketFactory());
-  }
-
-  @Test
-  public void testAlwaysTrustManager() {
-    HttpsTrust.AlwaysTrustManager manager = new HttpsTrust.AlwaysTrustManager();
-    assertThat(manager.getAcceptedIssuers()).isEmpty();
-    // does nothing
-    manager.checkClientTrusted(null, null);
-    manager.checkServerTrusted(null, null);
-  }
-
-  @Test
-  public void failOnError() throws Exception {
-    HttpsTrust.Ssl context = mock(HttpsTrust.Ssl.class);
-    KeyManagementException cause = new KeyManagementException("foo");
-    when(context.newFactory(any(TrustManager.class))).thenThrow(cause);
-
-    try {
-      new HttpsTrust(context);
-      fail();
-    } catch (IllegalStateException e) {
-      assertThat(e.getMessage()).isEqualTo("Fail to build SSL factory");
-      assertThat(e.getCause()).isSameAs(cause);
-    }
-  }
-
-  private HttpsURLConnection newHttpsConnection() throws IOException {
-    return (HttpsURLConnection) new URL("https://localhost").openConnection();
-  }
-}