aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch/src/main/java/org
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2015-12-02 11:40:43 +0100
committerSimon Brandhof <simon.brandhof@sonarsource.com>2015-12-02 14:16:49 +0100
commit92b68fdb6bca9347e153424fb4f79ceae400fc3d (patch)
tree78c7cd28e588d4f69c37575d7d84d14c0e45ec1f /sonar-batch/src/main/java/org
parentb4201256a7e4d8b153ecf0cb074f6e264df67f17 (diff)
downloadsonarqube-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.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchWsClient.java130
-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.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/WsClientLoggingInterceptor.java90
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/StrategyWSLoaderProvider.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java24
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java49
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java4
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;