diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-12-02 11:40:43 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-12-02 14:16:49 +0100 |
commit | 92b68fdb6bca9347e153424fb4f79ceae400fc3d (patch) | |
tree | 78c7cd28e588d4f69c37575d7d84d14c0e45ec1f /sonar-batch/src/main/java/org | |
parent | b4201256a7e4d8b153ecf0cb074f6e264df67f17 (diff) | |
download | sonarqube-92b68fdb6bca9347e153424fb4f79ceae400fc3d.tar.gz sonarqube-92b68fdb6bca9347e153424fb4f79ceae400fc3d.zip |
ws-client should not throw HttpException by default
Diffstat (limited to 'sonar-batch/src/main/java/org')
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java | 4 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java | 9 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClient.java | 130 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClientProvider.java (renamed from sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientProvider.java) | 13 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java | 2 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientLoggingInterceptor.java | 90 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java | 4 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java | 24 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java | 49 | ||||
-rw-r--r-- | sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java | 4 |
10 files changed, 186 insertions, 143 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java b/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java index 328478d3f87..7ca47ae787a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/analysis/AnalysisWSLoaderProvider.java @@ -21,15 +21,15 @@ package org.sonar.batch.analysis; import org.picocontainer.injectors.ProviderAdapter; import org.sonar.api.batch.AnalysisMode; +import org.sonar.batch.bootstrap.BatchWsClient; import org.sonar.batch.cache.WSLoader; import org.sonar.batch.cache.WSLoader.LoadStrategy; import org.sonar.home.cache.PersistentCache; -import org.sonarqube.ws.client.WsClient; public class AnalysisWSLoaderProvider extends ProviderAdapter { private WSLoader wsLoader; - public WSLoader provide(AnalysisMode mode, PersistentCache cache, WsClient client) { + public WSLoader provide(AnalysisMode mode, PersistentCache cache, BatchWsClient client) { if (wsLoader == null) { // recreate cache directory if needed for this analysis cache.reconfigure(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java index 56b4199e8e6..950d3e9baf3 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java @@ -42,7 +42,6 @@ import org.sonar.core.platform.RemotePlugin; import org.sonar.core.platform.RemotePluginFile; import org.sonar.home.cache.FileCache; import org.sonarqube.ws.client.GetRequest; -import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.WsResponse; import static java.lang.String.format; @@ -59,9 +58,9 @@ public class BatchPluginInstaller implements PluginInstaller { private final WSLoader wsLoader; private final FileCache fileCache; private final BatchPluginPredicate pluginPredicate; - private final WsClient wsClient; + private final BatchWsClient wsClient; - public BatchPluginInstaller(WSLoader wsLoader, WsClient wsClient, FileCache fileCache, BatchPluginPredicate pluginPredicate) { + public BatchPluginInstaller(WSLoader wsLoader, BatchWsClient wsClient, FileCache fileCache, BatchPluginPredicate pluginPredicate) { this.wsLoader = wsLoader; this.fileCache = fileCache; this.pluginPredicate = pluginPredicate; @@ -151,8 +150,8 @@ public class BatchPluginInstaller implements PluginInstaller { LOG.info("Download {}", filename); } - WsResponse response = wsClient.wsConnector().call(new GetRequest(url)); - try (InputStream stream = response.getContentStream()) { + WsResponse response = wsClient.call(new GetRequest(url)); + try (InputStream stream = response.contentStream()) { FileUtils.copyInputStreamToFile(stream, toFile); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClient.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClient.java new file mode 100644 index 00000000000..16bac82b84f --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClient.java @@ -0,0 +1,130 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.batch.bootstrap; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.net.HttpURLConnection; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.CoreProperties; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.api.utils.log.Profiler; +import org.sonarqube.ws.client.HttpException; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.WsConnector; +import org.sonarqube.ws.client.WsRequest; +import org.sonarqube.ws.client.WsResponse; + +import static java.lang.String.format; + +public class BatchWsClient { + + private static final Logger LOG = Loggers.get(BatchWsClient.class); + + private final WsClient target; + private final boolean hasCredentials; + private final String publicBaseUrl; + + public BatchWsClient(WsClient target, boolean hasCredentials, @Nullable String publicBaseUrl) { + this.target = target; + this.hasCredentials = hasCredentials; + if (StringUtils.isBlank(publicBaseUrl)) { + this.publicBaseUrl = target.wsConnector().baseUrl(); + } else { + this.publicBaseUrl = publicBaseUrl.replaceAll("(/)+$", "") + "/"; + } + } + + /** + * @throws IllegalStateException if the request could not be executed due to + * a connectivity problem or timeout. Because networks can + * fail during an exchange, it is possible that the remote server + * accepted the request before the failure + * @throws HttpException if the response code is not in range [200..300) + */ + public WsResponse call(WsRequest request) { + Profiler profiler = Profiler.createIfDebug(LOG).start(); + WsResponse response = target.wsConnector().call(request); + profiler.stopDebug(format("%s %d %s", request.getMethod(), response.code(), response.requestUrl())); + failIfUnauthorized(response); + return response; + } + + public String baseUrl() { + return target.wsConnector().baseUrl(); + } + + /** + * The public URL is optionally configured on server. If not, then the regular {@link #baseUrl()} is returned. + * URL has a trailing slash. + * See https://jira.sonarsource.com/browse/SONAR-4239 + */ + public String publicBaseUrl() { + return publicBaseUrl; + } + + @VisibleForTesting + WsConnector wsConnector() { + return target.wsConnector(); + } + + private void failIfUnauthorized(WsResponse response) { + if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { + if (hasCredentials) { + // credentials are not valid + throw MessageException.of(format("Not authorized. Please check the properties %s and %s.", + CoreProperties.LOGIN, CoreProperties.PASSWORD)); + } + // not authenticated - see https://jira.sonarsource.com/browse/SONAR-4048 + throw MessageException.of(format("Not authorized. Analyzing this project requires to be authenticated. " + + "Please provide the values of the properties %s and %s.", CoreProperties.LOGIN, CoreProperties.PASSWORD)); + + } + if (response.code() == HttpURLConnection.HTTP_FORBIDDEN) { + // SONAR-4397 Details are in response content + throw MessageException.of(tryParseAsJsonError(response.content())); + } + response.failIfNotSuccessful(); + } + + private static String tryParseAsJsonError(String responseContent) { + try { + JsonParser parser = new JsonParser(); + JsonObject obj = parser.parse(responseContent).getAsJsonObject(); + JsonArray errors = obj.getAsJsonArray("errors"); + List<String> errorMessages = new ArrayList<>(); + for (JsonElement e : errors) { + errorMessages.add(e.getAsJsonObject().get("msg").getAsString()); + } + return Joiner.on(", ").join(errorMessages); + } catch (Exception e) { + return responseContent; + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientProvider.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClientProvider.java index 78e50cc2ca2..a8ac402da35 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClientProvider.java @@ -25,22 +25,21 @@ import org.sonar.api.batch.BatchSide; import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonarqube.ws.client.HttpConnector; import org.sonarqube.ws.client.HttpWsClient; -import org.sonarqube.ws.client.WsClient; import static java.lang.Integer.parseInt; import static java.lang.String.valueOf; import static org.apache.commons.lang.StringUtils.defaultIfBlank; @BatchSide -public class WsClientProvider extends ProviderAdapter { +public class BatchWsClientProvider extends ProviderAdapter { static final int CONNECT_TIMEOUT_MS = 5_000; static final String READ_TIMEOUT_SEC_PROPERTY = "sonar.ws.timeout"; static final int DEFAULT_READ_TIMEOUT_SEC = 60; - private HttpWsClient wsClient; + private BatchWsClient wsClient; - public synchronized WsClient provide(final GlobalProperties settings, final EnvironmentInformation env) { + public synchronized BatchWsClient provide(final GlobalProperties settings, final EnvironmentInformation env) { if (wsClient == null) { String url = defaultIfBlank(settings.property("sonar.host.url"), CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE); HttpConnector.Builder builder = new HttpConnector.Builder(); @@ -48,15 +47,15 @@ public class WsClientProvider extends ProviderAdapter { // TODO proxy String timeoutSec = defaultIfBlank(settings.property(READ_TIMEOUT_SEC_PROPERTY), valueOf(DEFAULT_READ_TIMEOUT_SEC)); + String login = defaultIfBlank(settings.property(CoreProperties.LOGIN), null); builder .readTimeoutMilliseconds(parseInt(timeoutSec) * 1_000) .connectTimeoutMilliseconds(CONNECT_TIMEOUT_MS) .userAgent(env.toString()) .url(url) - .credentials(settings.property(CoreProperties.LOGIN), settings.property(CoreProperties.PASSWORD)) - .interceptor(new WsClientLoggingInterceptor()); + .credentials(login, settings.property(CoreProperties.PASSWORD)); - wsClient = new HttpWsClient(builder.build()); + wsClient = new BatchWsClient(new HttpWsClient(builder.build()), login != null, settings.property(CoreProperties.SERVER_BASE_URL)); } return wsClient; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java index 40b5cacb9d1..0440645b5c3 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java @@ -91,7 +91,7 @@ public class GlobalContainer extends ComponentContainer { CachesManager.class, GlobalSettings.class, - new WsClientProvider(), + new BatchWsClientProvider(), DefaultServer.class, new GlobalTempFolderProvider(), DefaultHttpDownloader.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientLoggingInterceptor.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientLoggingInterceptor.java deleted file mode 100644 index f94bf084ee9..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientLoggingInterceptor.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.batch.bootstrap; - -import com.google.common.base.Joiner; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.util.ArrayList; -import java.util.List; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.CoreProperties; -import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.api.utils.log.Profiler; - -import static java.lang.String.format; - -public class WsClientLoggingInterceptor implements Interceptor { - - private static final Logger LOG = Loggers.get(WsClientLoggingInterceptor.class); - - @Override - public Response intercept(Chain chain) throws IOException { - Response response = logAndSendRequest(chain); - if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { - if (StringUtils.isBlank(response.request().header("Authorization"))) { - // not authenticated - see https://jira.sonarsource.com/browse/SONAR-4048 - throw MessageException.of(format("Not authorized. Analyzing this project requires to be authenticated. " + - "Please provide the values of the properties %s and %s.", CoreProperties.LOGIN, CoreProperties.PASSWORD)); - } - // credentials are not valid - throw MessageException.of(format("Not authorized. Please check the properties %s and %s.", - CoreProperties.LOGIN, CoreProperties.PASSWORD)); - } - if (response.code() == HttpURLConnection.HTTP_FORBIDDEN) { - // SONAR-4397 Details are in response content - throw MessageException.of(tryParseAsJsonError(response.body().string())); - } - return response; - } - - private Response logAndSendRequest(Chain chain) throws IOException { - Request request = chain.request(); - Response response; - Profiler profiler = Profiler.createIfDebug(LOG).startTrace(format("%s %s", request.method(), request.url())); - response = chain.proceed(request); - profiler.stopDebug(format("%s %d %s", request.method(), response.code(), request.url())); - return response; - } - - private static String tryParseAsJsonError(String responseContent) { - try { - JsonParser parser = new JsonParser(); - JsonObject obj = parser.parse(responseContent).getAsJsonObject(); - JsonArray errors = obj.getAsJsonArray("errors"); - List<String> errorMessages = new ArrayList<>(); - for (JsonElement e : errors) { - errorMessages.add(e.getAsJsonObject().get("msg").getAsString()); - } - return Joiner.on(", ").join(errorMessages); - } catch (Exception e) { - return responseContent; - } - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java b/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java index e7c573753df..e6f7d6b00cb 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java @@ -20,9 +20,9 @@ package org.sonar.batch.cache; import org.picocontainer.injectors.ProviderAdapter; +import org.sonar.batch.bootstrap.BatchWsClient; import org.sonar.batch.cache.WSLoader.LoadStrategy; import org.sonar.home.cache.PersistentCache; -import org.sonarqube.ws.client.WsClient; public class StrategyWSLoaderProvider extends ProviderAdapter { private final LoadStrategy strategy; @@ -32,7 +32,7 @@ public class StrategyWSLoaderProvider extends ProviderAdapter { this.strategy = strategy; } - public WSLoader provide(PersistentCache cache, WsClient client) { + public WSLoader provide(PersistentCache cache, BatchWsClient client) { if (wsLoader == null) { wsLoader = new WSLoader(strategy, cache, client); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java b/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java index 69e7c14538f..9864e574f9b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java @@ -26,12 +26,13 @@ import java.nio.charset.StandardCharsets; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.commons.io.IOUtils; +import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; +import org.sonar.batch.bootstrap.BatchWsClient; import org.sonar.home.cache.PersistentCache; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.HttpException; -import org.sonarqube.ws.client.WsClient; import static org.sonar.batch.cache.WSLoader.ServerStatus.ACCESSIBLE; import static org.sonar.batch.cache.WSLoader.ServerStatus.NOT_ACCESSIBLE; @@ -50,7 +51,7 @@ public class WSLoader { } private final LoadStrategy defautLoadStrategy; - private final WsClient client; + private final BatchWsClient wsClient; private final PersistentCache cache; private ServerStatus serverStatus; @@ -58,7 +59,7 @@ public class WSLoader { @Override public String load(String id) throws IOException { GetRequest getRequest = new GetRequest(id); - try (Reader reader = client.wsConnector().call(getRequest).getContentReader()) { + try (Reader reader = wsClient.call(getRequest).contentReader()) { String str = IOUtils.toString(reader); try { cache.put(id, str.getBytes(StandardCharsets.UTF_8)); @@ -81,7 +82,7 @@ public class WSLoader { @Override public InputStream load(String id) throws IOException { GetRequest getRequest = new GetRequest(id); - try (InputStream is = client.wsConnector().call(getRequest).getContentStream()) { + try (InputStream is = wsClient.call(getRequest).contentStream()) { try { cache.put(id, is); } catch (IOException e) { @@ -111,11 +112,11 @@ public class WSLoader { } } - public WSLoader(LoadStrategy strategy, PersistentCache cache, WsClient client) { + public WSLoader(LoadStrategy strategy, PersistentCache cache, BatchWsClient wsClient) { this.defautLoadStrategy = strategy; this.serverStatus = UNKNOWN; this.cache = cache; - this.client = client; + this.wsClient = wsClient; } @Nonnull @@ -193,7 +194,7 @@ public class WSLoader { throw new IllegalStateException(FAIL_MSG, serverNotAvailable.getCause()); } } - throw new IllegalStateException("Server is not available: " + client.wsConnector().baseUrl(), serverNotAvailable.getCause()); + throw new IllegalStateException("Server is not available: " + wsClient.baseUrl(), serverNotAvailable.getCause()); } } @@ -201,7 +202,6 @@ public class WSLoader { T load(String id) throws IOException; } - @Nonnull private <T> WSLoaderResult<T> loadFromCache(String id, DataLoader<T> loader) throws NotAvailableException { T result; @@ -217,7 +217,6 @@ public class WSLoader { return new WSLoaderResult<>(result, true); } - @Nonnull private <T> WSLoaderResult<T> loadFromServer(String id, DataLoader<T> loader) throws NotAvailableException { if (isOffline()) { throw new NotAvailableException("Server not available"); @@ -226,11 +225,10 @@ public class WSLoader { T t = loader.load(id); switchToOnline(); return new WSLoaderResult<>(t, false); + } catch (HttpException | MessageException e) { + // fail fast if it could connect but there was a application-level error + throw e; } catch (IllegalStateException e) { - if (e.getCause() instanceof HttpException) { - // fail fast if it could connect but there was a application-level error - throw e; - } switchToOffline(); throw new NotAvailableException(e); } catch (Exception e) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java index 209dd29712f..524a9a034f5 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java @@ -20,10 +20,12 @@ package org.sonar.batch.report; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Throwables; import com.google.common.io.Files; import com.squareup.okhttp.HttpUrl; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.Writer; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -42,11 +44,13 @@ import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.text.JsonWriter; import org.sonar.batch.analysis.DefaultAnalysisMode; +import org.sonar.batch.bootstrap.BatchWsClient; import org.sonar.batch.protocol.output.BatchReportWriter; import org.sonar.batch.scan.ImmutableProjectReactor; +import org.sonarqube.ws.MediaTypes; import org.sonarqube.ws.WsCe; -import org.sonarqube.ws.client.WsClient; -import org.sonarqube.ws.client.ce.SubmitWsRequest; +import org.sonarqube.ws.client.PostRequest; +import org.sonarqube.ws.client.WsResponse; import static org.apache.commons.lang.StringUtils.defaultIfBlank; @@ -60,7 +64,7 @@ public class ReportPublisher implements Startable { public static final String METADATA_DUMP_FILENAME = "analysis-details.json"; private final Settings settings; - private final WsClient wsClient; + private final BatchWsClient wsClient; private final AnalysisContextReportPublisher contextPublisher; private final ImmutableProjectReactor projectReactor; private final DefaultAnalysisMode analysisMode; @@ -70,7 +74,7 @@ public class ReportPublisher implements Startable { private File reportDir; private BatchReportWriter writer; - public ReportPublisher(Settings settings, WsClient wsClient, AnalysisContextReportPublisher contextPublisher, + public ReportPublisher(Settings settings, BatchWsClient wsClient, AnalysisContextReportPublisher contextPublisher, ImmutableProjectReactor projectReactor, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers) { this.settings = settings; this.wsClient = wsClient; @@ -145,15 +149,22 @@ public class ReportPublisher implements Startable { LOG.debug("Upload report"); long startTime = System.currentTimeMillis(); ProjectDefinition projectDefinition = projectReactor.getRoot(); - SubmitWsRequest submitRequest = new SubmitWsRequest(); - submitRequest.setProjectKey(projectDefinition.getKey()); - submitRequest.setProjectName(projectDefinition.getName()); - submitRequest.setProjectBranch(projectDefinition.getBranch()); - submitRequest.setReport(report); - WsCe.SubmitResponse submitResponse = wsClient.computeEngine().submit(submitRequest); - long stopTime = System.currentTimeMillis(); - LOG.info("Analysis report uploaded in " + (stopTime - startTime) + "ms"); - return submitResponse.getTaskId(); + PostRequest.Part filePart = new PostRequest.Part(MediaTypes.ZIP, report); + PostRequest post = new PostRequest("api/ce/submit") + .setMediaType(MediaTypes.PROTOBUF) + .setParam("projectKey", projectDefinition.getKey()) + .setParam("projectName", projectDefinition.getName()) + .setParam("projectBranch", projectDefinition.getBranch()) + .setPart("report", filePart); + WsResponse response = wsClient.call(post).failIfNotSuccessful(); + try (InputStream protobuf = response.contentStream()) { + return WsCe.SubmitResponse.parser().parseFrom(protobuf).getTaskId(); + } catch (Exception e) { + throw Throwables.propagate(e); + } finally { + long stopTime = System.currentTimeMillis(); + LOG.info("Analysis report uploaded in " + (stopTime - startTime) + "ms"); + } } @VisibleForTesting @@ -165,13 +176,13 @@ public class ReportPublisher implements Startable { String effectiveKey = projectReactor.getRoot().getKeyWithBranch(); metadata.put("projectKey", effectiveKey); - URL dashboardUrl = HttpUrl.parse(publicUrl()).newBuilder() + URL dashboardUrl = HttpUrl.parse(wsClient.publicBaseUrl()).newBuilder() .addPathSegment("dashboard").addPathSegment("index").addPathSegment(effectiveKey) .build() .url(); metadata.put("dashboardUrl", dashboardUrl.toExternalForm()); - URL taskUrl = HttpUrl.parse(publicUrl()).newBuilder() + URL taskUrl = HttpUrl.parse(wsClient.publicBaseUrl()).newBuilder() .addPathSegment("api").addPathSegment("ce").addPathSegment("task") .addQueryParameter("id", taskId) .build() @@ -202,12 +213,4 @@ public class ReportPublisher implements Startable { throw new IllegalStateException("Unable to dump " + file, e); } } - - /** - * The public URL is optionally configured on server. If not, then the regular URL is returned. - * See https://jira.sonarsource.com/browse/SONAR-4239 - */ - private String publicUrl() { - return defaultIfBlank(settings.getString(CoreProperties.SERVER_BASE_URL), wsClient.wsConnector().baseUrl()); - } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java index 3a00c304aaa..8168c676b8a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java @@ -36,6 +36,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.mutable.MutableBoolean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.sonar.api.utils.MessageException; import org.sonar.batch.cache.WSLoader; import org.sonar.batch.cache.WSLoaderResult; import org.sonar.batch.util.BatchUtils; @@ -88,6 +89,9 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad HttpException http = (HttpException) t; return http.code() != HttpURLConnection.HTTP_NOT_FOUND; } + if (t instanceof MessageException) { + return true; + } } return false; |