// authenticate
WsClient wsClient = new HttpWsClient(new HttpConnector.Builder().url(ORCHESTRATOR.getServer().getUrl()).credentials(login, password).build());
WsResponse response = wsClient.wsConnector().call(new GetRequest("api/authentication/validate"));
- assertThat(response.getContent()).isEqualTo("{\"valid\":true}");
+ assertThat(response.content()).isEqualTo("{\"valid\":true}");
}
@Test
WsResponse response = wsClient.wsConnector().call(new GetRequest("api/authentication/validate"));
- assertThat(response.getContent()).isEqualTo("{\"valid\":true}");
+ assertThat(response.content()).isEqualTo("{\"valid\":true}");
}
/**
// authenticate
WsClient wsClient = new HttpWsClient(new HttpConnector.Builder().url(ORCHESTRATOR.getServer().getUrl()).credentials(login, password).build());
WsResponse response = wsClient.wsConnector().call(new GetRequest("api/authentication/validate"));
- assertThat(response.getContent()).isEqualTo("{\"valid\":false}");
+ assertThat(response.content()).isEqualTo("{\"valid\":false}");
}
@Test
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();
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;
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;
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);
}
}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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 org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.CoreProperties;
+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 static java.lang.Integer.parseInt;
+import static java.lang.String.valueOf;
+import static org.apache.commons.lang.StringUtils.defaultIfBlank;
+
+@BatchSide
+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 BatchWsClient wsClient;
+
+ 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();
+
+ // 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(login, settings.property(CoreProperties.PASSWORD));
+
+ wsClient = new BatchWsClient(new HttpWsClient(builder.build()), login != null, settings.property(CoreProperties.SERVER_BASE_URL));
+ }
+ return wsClient;
+ }
+}
CachesManager.class,
GlobalSettings.class,
- new WsClientProvider(),
+ new BatchWsClientProvider(),
DefaultServer.class,
new GlobalTempFolderProvider(),
DefaultHttpDownloader.class,
+++ /dev/null
-/*
- * 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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 org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.CoreProperties;
-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 {
-
- 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;
-
- public synchronized WsClient 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();
-
- // TODO proxy
-
- String timeoutSec = defaultIfBlank(settings.property(READ_TIMEOUT_SEC_PROPERTY), valueOf(DEFAULT_READ_TIMEOUT_SEC));
- 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());
-
- wsClient = new HttpWsClient(builder.build());
- }
- return wsClient;
- }
-}
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;
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);
}
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;
}
private final LoadStrategy defautLoadStrategy;
- private final WsClient client;
+ private final BatchWsClient wsClient;
private final PersistentCache cache;
private ServerStatus serverStatus;
@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));
@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) {
}
}
- 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
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());
}
}
T load(String id) throws IOException;
}
- @Nonnull
private <T> WSLoaderResult<T> loadFromCache(String id, DataLoader<T> loader) throws NotAvailableException {
T result;
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");
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) {
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;
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;
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;
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;
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
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()
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());
- }
}
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;
HttpException http = (HttpException) t;
return http.code() != HttpURLConnection.HTTP_NOT_FOUND;
}
+ if (t instanceof MessageException) {
+ return true;
+ }
}
return false;
*/
package org.sonar.batch.analysis;
-import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
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;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
public class AnalysisWSLoaderProviderTest {
- @Mock
- private PersistentCache cache;
- @Mock
- private WsClient client;
+ PersistentCache cache = mock(PersistentCache.class);
+ BatchWsClient wsClient = mock(BatchWsClient.class);
+ AnalysisMode mode = mock(AnalysisMode.class);
- @Mock
- private AnalysisMode mode;
-
- private AnalysisWSLoaderProvider loaderProvider;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- loaderProvider = new AnalysisWSLoaderProvider();
- }
+ AnalysisWSLoaderProvider underTest = new AnalysisWSLoaderProvider();
@Test
public void testDefault() {
- WSLoader loader = loaderProvider.provide(mode, cache, client);
+ WSLoader loader = underTest.provide(mode, cache, wsClient);
assertThat(loader.getDefaultStrategy()).isEqualTo(LoadStrategy.SERVER_ONLY);
}
}
import org.sonar.batch.cache.WSLoaderResult;
import org.sonar.core.platform.RemotePlugin;
import org.sonar.home.cache.FileCache;
-import org.sonarqube.ws.client.WsClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
public ExpectedException thrown = ExpectedException.none();
FileCache fileCache = mock(FileCache.class);
- WsClient wsClient = mock(WsClient.class);
+ BatchWsClient wsClient = mock(BatchWsClient.class);
BatchPluginPredicate pluginPredicate = mock(BatchPluginPredicate.class);
@Test
WSLoader wsLoader = mock(WSLoader.class);
when(wsLoader.loadString("/deploy/plugins/index.txt")).thenReturn(new WSLoaderResult<>("checkstyle\nsqale", true));
- BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, wsClient, fileCache, pluginPredicate);
+ BatchPluginInstaller underTest = new BatchPluginInstaller(wsLoader, wsClient, fileCache, pluginPredicate);
- List<RemotePlugin> remotePlugins = installer.listRemotePlugins();
+ List<RemotePlugin> remotePlugins = underTest.listRemotePlugins();
assertThat(remotePlugins).extracting("key").containsOnly("checkstyle", "sqale");
}
when(fileCache.get(eq("checkstyle-plugin.jar"), eq("fakemd5_1"), any(FileCache.Downloader.class))).thenReturn(pluginJar);
WSLoader wsLoader = mock(WSLoader.class);
- BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, wsClient, fileCache, pluginPredicate);
+ BatchPluginInstaller underTest = new BatchPluginInstaller(wsLoader, wsClient, fileCache, pluginPredicate);
RemotePlugin remote = new RemotePlugin("checkstyle").setFile("checkstyle-plugin.jar", "fakemd5_1");
- File file = installer.download(remote);
+ File file = underTest.download(remote);
assertThat(file).isEqualTo(pluginJar);
}
--- /dev/null
+/*
+ * 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 java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonarqube.ws.client.HttpConnector;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class BatchWsClientProviderTest {
+
+ BatchWsClientProvider underTest = new BatchWsClientProvider();
+ EnvironmentInformation env = new EnvironmentInformation("Maven Plugin", "2.3");
+
+ @Test
+ public void provide_client_with_default_settings() {
+ GlobalProperties settings = new GlobalProperties(new HashMap<String, String>());
+
+ BatchWsClient client = underTest.provide(settings, env);
+
+ assertThat(client).isNotNull();
+ assertThat(client.baseUrl()).isEqualTo("http://localhost:9000/");
+ assertThat(client.publicBaseUrl()).isEqualTo("http://localhost:9000/");
+ HttpConnector httpConnector = (HttpConnector) client.wsConnector();
+ assertThat(httpConnector.baseUrl()).isEqualTo("http://localhost:9000/");
+ assertThat(httpConnector.okHttpClient().getProxy()).isNull();
+ assertThat(httpConnector.okHttpClient().getConnectTimeout()).isEqualTo(5_000);
+ assertThat(httpConnector.okHttpClient().getReadTimeout()).isEqualTo(60_000);
+ assertThat(httpConnector.userAgent()).isEqualTo("Maven Plugin/2.3");
+ }
+
+ @Test
+ public void provide_client_with_custom_settings() {
+ Map<String, String> props = new HashMap<>();
+ props.put("sonar.host.url", "https://here/sonarqube");
+ props.put("sonar.login", "theLogin");
+ props.put("sonar.password", "thePassword");
+ props.put("sonar.ws.timeout", "42");
+ GlobalProperties settings = new GlobalProperties(props);
+
+ BatchWsClient client = underTest.provide(settings, env);
+
+ assertThat(client).isNotNull();
+ HttpConnector httpConnector = (HttpConnector) client.wsConnector();
+ assertThat(httpConnector.baseUrl()).isEqualTo("https://here/sonarqube/");
+ assertThat(httpConnector.okHttpClient().getProxy()).isNull();
+ assertThat(httpConnector.userAgent()).isEqualTo("Maven Plugin/2.3");
+ }
+
+ @Test
+ public void build_singleton() {
+ GlobalProperties settings = new GlobalProperties(new HashMap<String, String>());
+ BatchWsClient first = underTest.provide(settings, env);
+ BatchWsClient second = underTest.provide(settings, env);
+ assertThat(first).isSameAs(second);
+ }
+}
--- /dev/null
+/*
+ * 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 java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.MockWsResponse;
+import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.WsRequest;
+import org.sonarqube.ws.client.WsResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class BatchWsClientTest {
+
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ WsClient wsClient = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
+
+ @Test
+ public void define_public_url() {
+ when(wsClient.wsConnector().baseUrl()).thenReturn("https://local/");
+ BatchWsClient underTest = new BatchWsClient(wsClient, true, "https://public/");
+ assertThat(underTest.baseUrl()).isEqualTo("https://local/");
+ assertThat(underTest.publicBaseUrl()).isEqualTo("https://public/");
+ }
+
+ /**
+ * Returned URL has trailing slash, even if configured URL doesn't have.
+ * That's useful for {@link com.squareup.okhttp.HttpUrl}
+ */
+ @Test
+ public void public_url_has_trailing_slash() {
+ BatchWsClient underTest = new BatchWsClient(wsClient, true, "https://public");
+ assertThat(underTest.publicBaseUrl()).isEqualTo("https://public/");
+ }
+
+
+ @Test
+ public void public_url_is_the_base_url_by_default() {
+ when(wsClient.wsConnector().baseUrl()).thenReturn("https://local/");
+ BatchWsClient underTest = new BatchWsClient(wsClient, true, null);
+ assertThat(underTest.publicBaseUrl()).isEqualTo("https://local/");
+ }
+
+ @Test
+ public void log_and_profile_request_if_debug_level() throws Exception {
+ WsRequest request = newRequest();
+ WsResponse response = newResponse().setRequestUrl("https://local/api/issues/search");
+ when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+ logTester.setLevel(LoggerLevel.DEBUG);
+ BatchWsClient underTest = new BatchWsClient(wsClient, false, null);
+
+ WsResponse result = underTest.call(request);
+
+ // do not fail the execution -> interceptor returns the response
+ assertThat(result).isSameAs(response);
+
+ // check logs
+ List<String> debugLogs = logTester.logs(LoggerLevel.DEBUG);
+ assertThat(debugLogs).hasSize(1);
+ assertThat(debugLogs.get(0)).contains("GET 200 https://local/api/issues/search | time=");
+ }
+
+ @Test
+ public void fail_if_requires_credentials() throws Exception {
+ expectedException.expect(MessageException.class);
+ expectedException
+ .expectMessage("Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
+
+ WsRequest request = newRequest();
+ WsResponse response = newResponse().setCode(401);
+ when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+ new BatchWsClient(wsClient, false, null).call(request);
+ }
+
+ @Test
+ public void fail_if_credentials_are_not_valid() throws Exception {
+ expectedException.expect(MessageException.class);
+ expectedException.expectMessage("Not authorized. Please check the properties sonar.login and sonar.password.");
+
+ WsRequest request = newRequest();
+ WsResponse response = newResponse().setCode(401);
+ when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+ new BatchWsClient(wsClient, /* credentials are configured */true, null).call(request);
+ }
+
+ @Test
+ public void fail_if_requires_permission() throws Exception {
+ expectedException.expect(MessageException.class);
+ expectedException.expectMessage("missing scan permission, missing another permission");
+
+ WsRequest request = newRequest();
+ WsResponse response = newResponse()
+ .setCode(403)
+ .setContent("{\"errors\":[{\"msg\":\"missing scan permission\"}, {\"msg\":\"missing another permission\"}]}");
+ when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+ new BatchWsClient(wsClient, true, null).call(request);
+ }
+
+ private MockWsResponse newResponse() {
+ return new MockWsResponse().setRequestUrl("https://local/api/issues/search");
+ }
+
+ private WsRequest newRequest() {
+ return new GetRequest("api/issues/search");
+ }
+}
+++ /dev/null
-/*
- * 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.squareup.okhttp.Interceptor;
-import com.squareup.okhttp.MediaType;
-import com.squareup.okhttp.Protocol;
-import com.squareup.okhttp.Request;
-import com.squareup.okhttp.Response;
-import com.squareup.okhttp.ResponseBody;
-import java.util.List;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.MessageException;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class WsClientLoggingInterceptorTest {
-
- @Rule
- public LogTester logTester = new LogTester();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- WsClientLoggingInterceptor underTest = new WsClientLoggingInterceptor();
- Interceptor.Chain chain = mock(Interceptor.Chain.class);
-
- @Test
- public void log_and_profile_request_if_debug_level() throws Exception {
- Request request = newRequest();
- Response response = newResponse(request, 200, "");
- when(chain.request()).thenReturn(request);
- when(chain.proceed(request)).thenReturn(response);
-
- logTester.setLevel(LoggerLevel.DEBUG);
- Response result = underTest.intercept(chain);
-
- // do not fail the execution -> interceptor returns the response
- assertThat(result).isSameAs(response);
-
- // check logs
- List<String> debugLogs = logTester.logs(LoggerLevel.DEBUG);
- assertThat(debugLogs).hasSize(1);
- assertThat(debugLogs.get(0)).contains("GET 200 https://localhost:9000/api/issues/search | time=");
- List<String> traceLogs = logTester.logs(LoggerLevel.TRACE);
- assertThat(traceLogs).hasSize(1);
- assertThat(traceLogs.get(0)).isEqualTo("GET https://localhost:9000/api/issues/search");
- }
-
- @Test
- public void fail_if_requires_authentication() throws Exception {
- expectedException.expect(MessageException.class);
- expectedException
- .expectMessage("Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
-
- Request request = newRequest();
- Response response = newResponse(request, 401, "");
- when(chain.request()).thenReturn(request);
- when(chain.proceed(request)).thenReturn(response);
-
- underTest.intercept(chain);
- }
-
- @Test
- public void fail_if_credentials_are_not_valid() throws Exception {
- expectedException.expect(MessageException.class);
- expectedException.expectMessage("Not authorized. Please check the properties sonar.login and sonar.password.");
-
- Request request = new Request.Builder()
- .url("https://localhost:9000/api/issues/search")
- .header("Authorization", "Basic BAD_CREDENTIALS")
- .get()
- .build();
- Response response = newResponse(request, 401, "");
- when(chain.request()).thenReturn(request);
- when(chain.proceed(request)).thenReturn(response);
-
- underTest.intercept(chain);
- }
-
- @Test
- public void fail_if_requires_permission() throws Exception {
- expectedException.expect(MessageException.class);
- expectedException.expectMessage("missing scan permission, missing another permission");
-
- Request request = newRequest();
- Response response = newResponse(request, 403, "{\"errors\":[{\"msg\":\"missing scan permission\"}, {\"msg\":\"missing another permission\"}]}");
- when(chain.request()).thenReturn(request);
- when(chain.proceed(request)).thenReturn(response);
-
- underTest.intercept(chain);
- }
-
- private Request newRequest() {
- return new Request.Builder().url("https://localhost:9000/api/issues/search").get().build();
- }
-
- private Response newResponse(Request getRequest, int code, String jsonBody) {
- return new Response.Builder().request(getRequest)
- .code(code)
- .protocol(Protocol.HTTP_1_1)
- .body(ResponseBody.create(MediaType.parse("application/json"), jsonBody))
- .build();
- }
-
-}
+++ /dev/null
-/*
- * 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 java.util.HashMap;
-import java.util.Map;
-import org.junit.Test;
-import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import org.sonarqube.ws.client.HttpConnector;
-import org.sonarqube.ws.client.WsClient;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.batch.bootstrap.WsClientProvider.CONNECT_TIMEOUT_MS;
-import static org.sonar.batch.bootstrap.WsClientProvider.DEFAULT_READ_TIMEOUT_SEC;
-
-public class WsClientProviderTest {
-
- WsClientProvider underTest = new WsClientProvider();
- EnvironmentInformation env = new EnvironmentInformation("Maven Plugin", "2.3");
-
- @Test
- public void provide_client_with_default_settings() {
- GlobalProperties settings = new GlobalProperties(new HashMap<String, String>());
-
- WsClient client = underTest.provide(settings, env);
-
- assertThat(client).isNotNull();
- HttpConnector httpConnector = (HttpConnector) client.wsConnector();
- assertThat(httpConnector.baseUrl()).isEqualTo("http://localhost:9000/");
- assertThat(httpConnector.okHttpClient().getProxy()).isNull();
- assertThat(httpConnector.okHttpClient().getConnectTimeout()).isEqualTo(5_000);
- assertThat(httpConnector.okHttpClient().getReadTimeout()).isEqualTo(60_000);
- assertThat(httpConnector.userAgent()).isEqualTo("Maven Plugin/2.3");
- assertThat(httpConnector.okHttpClient().interceptors())
- .hasSize(1)
- .hasOnlyElementsOfType(WsClientLoggingInterceptor.class);
- }
-
- @Test
- public void provide_client_with_custom_settings() {
- Map<String, String> props = new HashMap<>();
- props.put("sonar.host.url", "https://here/sonarqube");
- props.put("sonar.login", "theLogin");
- props.put("sonar.password", "thePassword");
- props.put("sonar.ws.timeout", "42");
- GlobalProperties settings = new GlobalProperties(props);
-
- WsClient client = underTest.provide(settings, env);
-
- assertThat(client).isNotNull();
- HttpConnector httpConnector = (HttpConnector) client.wsConnector();
- assertThat(httpConnector.baseUrl()).isEqualTo("https://here/sonarqube/");
- assertThat(httpConnector.okHttpClient().getProxy()).isNull();
- assertThat(httpConnector.userAgent()).isEqualTo("Maven Plugin/2.3");
- }
-
- @Test
- public void build_singleton() {
- GlobalProperties settings = new GlobalProperties(new HashMap<String, String>());
- WsClient first = underTest.provide(settings, env);
- WsClient second = underTest.provide(settings, env);
- assertThat(first).isSameAs(second);
- }
-}
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+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;
import static org.assertj.core.api.Assertions.assertThat;
private PersistentCache cache;
@Mock
- private WsClient client;
+ private BatchWsClient client;
@Before
public void setUp() {
import org.junit.rules.ExpectedException;
import org.mockito.InOrder;
import org.mockito.Mockito;
+import org.sonar.batch.bootstrap.BatchWsClient;
import org.sonar.batch.cache.WSLoader.LoadStrategy;
import org.sonar.home.cache.PersistentCache;
import org.sonarqube.ws.client.HttpException;
import org.sonarqube.ws.client.MockWsResponse;
-import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.WsConnector;
import org.sonarqube.ws.client.WsRequest;
@Rule
public ExpectedException exception = ExpectedException.none();
- WsClient ws = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
+ BatchWsClient ws = mock(BatchWsClient.class, Mockito.RETURNS_DEEP_STUBS);
PersistentCache cache = mock(PersistentCache.class);
@Test
public void put_stream_in_cache() throws IOException {
InputStream input = IOUtils.toInputStream("is");
- when(ws.wsConnector().call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(input));
+ when(ws.call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(input));
when(cache.getStream(ID)).thenReturn(input);
// SERVER_FIRST -> load from server then put to cache
WSLoaderResult<InputStream> result = underTest.loadStream(ID);
assertThat(result.get()).isEqualTo(input);
- WsConnector wsConnector = ws.wsConnector();
- InOrder inOrder = inOrder(wsConnector, cache);
- inOrder.verify(wsConnector).call(any(WsRequest.class));
+ InOrder inOrder = inOrder(ws, cache);
+ inOrder.verify(ws).call(any(WsRequest.class));
inOrder.verify(cache).put(eq(ID), any(InputStream.class));
inOrder.verify(cache).getStream(ID);
- verifyNoMoreInteractions(cache, wsConnector);
+ verifyNoMoreInteractions(cache, ws);
}
@Test
public void test_cache_strategy_fallback() throws IOException {
turnCacheEmpty();
- when(ws.wsConnector().call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
+ when(ws.call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
WSLoader loader = new WSLoader(LoadStrategy.CACHE_FIRST, cache, ws);
assertResult(loader.loadString(ID), serverValue, false);
- InOrder inOrder = inOrder(ws.wsConnector(), cache);
+ InOrder inOrder = inOrder(ws, cache);
inOrder.verify(cache).getString(ID);
- inOrder.verify(ws.wsConnector()).call(any(WsRequest.class));
+ inOrder.verify(ws).call(any(WsRequest.class));
}
@Test
assertResult(loader.loadString(ID), cacheValue, true);
- InOrder inOrder = inOrder(ws.wsConnector(), cache);
- inOrder.verify(ws.wsConnector()).call(any(WsRequest.class));
+ InOrder inOrder = inOrder(ws, cache);
+ inOrder.verify(ws).call(any(WsRequest.class));
inOrder.verify(cache).getString(ID);
}
@Test
public void test_put_cache() throws IOException {
- when(ws.wsConnector().call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
+ when(ws.call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
loader.loadString(ID);
verify(cache).put(ID, serverValue.getBytes());
@Test
public void test_throw_http_exceptions() {
- HttpException httpException = new HttpException("url", 500, "Internal Error");
- IllegalStateException wrapperException = new IllegalStateException(httpException);
-
- when(ws.wsConnector().call(any(WsRequest.class))).thenThrow(wrapperException);
+ when(ws.call(any(WsRequest.class))).thenThrow(new HttpException("url", 500));
WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
try {
loader.loadString(ID);
fail("IllegalStateException expected");
- } catch (IllegalStateException e) {
+ } catch (HttpException e) {
// cache should not be used
verifyNoMoreInteractions(cache);
}
@Test
public void test_server_strategy() throws IOException {
- when(ws.wsConnector().call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
+ when(ws.call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
assertResult(loader.loadString(ID), serverValue, false);
@Test
public void test_string() {
- when(ws.wsConnector().call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
+ when(ws.call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
assertResult(loader.loadString(ID), serverValue, false);
}
}
private void assertUsedServer(int times) {
- verify(ws.wsConnector(), times(times)).call(any(WsRequest.class));
+ verify(ws, times(times)).call(any(WsRequest.class));
}
private void assertResult(WSLoaderResult<String> result, String expected, boolean fromCache) {
}
private void turnServerOffline() {
- when(ws.wsConnector().call(any(WsRequest.class))).thenThrow(new IllegalStateException());
+ when(ws.call(any(WsRequest.class))).thenThrow(new IllegalStateException());
}
private void turnCacheEmpty() throws IOException {
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.bootstrap.BatchWsClient;
import org.sonar.batch.scan.ImmutableProjectReactor;
import org.sonar.test.JsonAssert;
-import org.sonarqube.ws.client.WsClient;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.assertj.core.api.Assertions.assertThat;
DefaultAnalysisMode mode = mock(DefaultAnalysisMode.class);
Settings settings = new Settings();
- WsClient wsClient = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
+ BatchWsClient wsClient = mock(BatchWsClient.class, Mockito.RETURNS_DEEP_STUBS);
ImmutableProjectReactor reactor = mock(ImmutableProjectReactor.class);
ProjectDefinition root;
AnalysisContextReportPublisher contextPublisher = mock(AnalysisContextReportPublisher.class);
public void setUp() {
root = ProjectDefinition.create().setKey("struts").setWorkDir(temp.getRoot());
when(reactor.getRoot()).thenReturn(root);
- when(wsClient.wsConnector().baseUrl()).thenReturn("https://localhost");
+ when(wsClient.baseUrl()).thenReturn("https://localhost/");
+ when(wsClient.publicBaseUrl()).thenReturn("https://public/");
}
@Test
underTest.logSuccess("TASK-123");
assertThat(logTester.logs(LoggerLevel.INFO))
- .contains("ANALYSIS SUCCESSFUL, you can browse https://localhost/dashboard/index/struts")
+ .contains("ANALYSIS SUCCESSFUL, you can browse https://public/dashboard/index/struts")
.contains("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report")
- .contains("More about the report processing at https://localhost/api/ce/task?id=TASK-123");
+ .contains("More about the report processing at https://public/api/ce/task?id=TASK-123");
File detailsFile = new File(temp.getRoot(), "analysis-details.json");
JsonAssert.assertJson(readFileToString(detailsFile)).isSimilarTo("{" +
"\"projectKey\": \"struts\"," +
- "\"dashboardUrl\": \"https://localhost/dashboard/index/struts\"," +
+ "\"dashboardUrl\": \"https://public/dashboard/index/struts\"," +
"\"ceTaskId\": \"TASK-123\"," +
- "\"ceTaskUrl\": \"https://localhost/api/ce/task?id=TASK-123\"" +
+ "\"ceTaskUrl\": \"https://public/api/ce/task?id=TASK-123\"" +
"}"
);
}
- @Test
- public void log_public_url_if_defined() throws IOException {
- settings.setProperty(CoreProperties.SERVER_BASE_URL, "https://publicserver/sonarqube");
- ReportPublisher underTest = new ReportPublisher(settings, wsClient, contextPublisher, reactor, mode, mock(TempFolder.class), new ReportPublisherStep[0]);
-
- underTest.logSuccess("TASK-123");
-
- assertThat(logTester.logs(LoggerLevel.INFO))
- .contains("ANALYSIS SUCCESSFUL, you can browse https://publicserver/sonarqube/dashboard/index/struts")
- .contains("More about the report processing at https://publicserver/sonarqube/api/ce/task?id=TASK-123");
-
- File detailsFile = new File(temp.getRoot(), "analysis-details.json");
- JsonAssert.assertJson(readFileToString(detailsFile)).isSimilarTo("{" +
- "\"projectKey\": \"struts\"," +
- "\"dashboardUrl\": \"https://publicserver/sonarqube/dashboard/index/struts\"," +
- "\"ceTaskId\": \"TASK-123\"," +
- "\"ceTaskUrl\": \"https://publicserver/sonarqube/api/ce/task?id=TASK-123\"" +
- "}"
- );
- }
-
@Test
public void log_but_not_dump_information_when_report_is_not_uploaded() {
ReportPublisher underTest = new ReportPublisher(settings, wsClient, contextPublisher, reactor, mode, mock(TempFolder.class), new ReportPublisherStep[0]);
@Test(expected = IllegalStateException.class)
public void failFastHttpError() {
- HttpException http = new HttpException("url", 403, "Forbidden");
+ HttpException http = new HttpException("url", 403);
IllegalStateException e = new IllegalStateException("http error", http);
when(wsLoader.loadStream(anyString())).thenThrow(e);
loader.load(PROJECT_KEY, false, null);
thrown.expect(MessageException.class);
thrown.expectMessage("http error");
- HttpException http = new HttpException("uri", 403, "Forbidden");
+ HttpException http = new HttpException("uri", 403);
MessageException e = MessageException.of("http error", http);
when(wsLoader.loadStream(anyString())).thenThrow(e);
loader.load(PROJECT_KEY, false, null);
--- /dev/null
+/*
+ * 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.sonarqube.ws.client;
+
+abstract class BaseResponse implements WsResponse {
+
+ @Override
+ public boolean isSuccessful() {
+ return code() >= 200 && code() < 300;
+ }
+
+ @Override
+ public WsResponse failIfNotSuccessful() {
+ if (!isSuccessful()) {
+ throw new HttpException(requestUrl(), code());
+ }
+ return this;
+ }
+
+}
protected <T extends Message> T call(BaseRequest request, Parser<T> parser) {
request.setMediaType(MediaTypes.PROTOBUF);
- WsResponse response = wsConnector.call(request);
+ WsResponse response = call(request);
return convert(response, parser);
}
protected WsResponse call(WsRequest request) {
- return wsConnector.call(request);
+ return wsConnector.call(request).failIfNotSuccessful();
}
public <T extends Message> T convert(WsResponse response, Parser<T> parser) {
- try (InputStream byteStream = response.getContentStream()) {
+ try (InputStream byteStream = response.contentStream()) {
// HTTP header "Content-Type" is not verified. It may be different than protobuf.
return parser.parseFrom(byteStream);
} catch (Exception e) {
- throw new IllegalStateException("Fail to parse protobuf response of " + response.getRequestUrl(), e);
+ throw new IllegalStateException("Fail to parse protobuf response of " + response.requestUrl(), e);
}
}
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.HttpUrl;
-import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Response;
import java.io.IOException;
import java.net.Proxy;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckForNull;
this.okHttpClient.setConnectTimeout(builder.connectTimeoutMs, TimeUnit.MILLISECONDS);
this.okHttpClient.setReadTimeout(builder.readTimeoutMs, TimeUnit.MILLISECONDS);
- this.okHttpClient.interceptors().addAll(builder.interceptors);
}
@Override
return baseUrl.url().toExternalForm();
}
- public OkHttpClient okHttpClient() {
- return okHttpClient;
- }
-
@CheckForNull
public String userAgent() {
return userAgent;
}
- @CheckForNull
- public String credentials() {
- return credentials;
+ public OkHttpClient okHttpClient() {
+ return okHttpClient;
}
@Override
Call call = okHttpClient.newCall(okRequest);
try {
Response okResponse = call.execute();
- if (!okResponse.isSuccessful()) {
- throw new HttpException(okRequest.urlString(), okResponse.code(), okResponse.message());
- }
return new HttpResponse(okResponse);
} catch (IOException e) {
throw new IllegalStateException("Fail to request " + okRequest.urlString(), e);
private String proxyPassword;
private int connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MILLISECONDS;
private int readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLISECONDS;
- private final List<Interceptor> interceptors = new ArrayList<>();
/**
* Optional User Agent
return this;
}
- /**
- * Adds a OkHttp interceptor, for example to log request URLs or response errors.
- * See https://github.com/square/okhttp/wiki/Interceptors
- */
- public Builder interceptor(Interceptor interceptor) {
- this.interceptors.add(interceptor);
- return this;
- }
-
public HttpConnector build() {
checkArgument(!isNullOrEmpty(url), "Server URL is not defined");
return new HttpConnector(this);
private final String url;
private final int code;
- public HttpException(String url, int code, String message) {
- super(String.format("Error %d on %s : %s", code, url, message));
+ public HttpException(String url, int code) {
+ super(String.format("Error %d on %s", code, url));
this.url = url;
this.code = code;
}
import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
-class HttpResponse implements WsResponse {
+class HttpResponse extends BaseResponse {
private final Response okResponse;
}
@Override
- public String getRequestUrl() {
+ public int code() {
+ return okResponse.code();
+ }
+
+ @Override
+ public String requestUrl() {
return okResponse.request().urlString();
}
}
@Override
- public String getContentType() {
+ public String contentType() {
return okResponse.header("Content-Type");
}
* Get stream of bytes
*/
@Override
- public InputStream getContentStream() {
+ public InputStream contentStream() {
try {
return okResponse.body().byteStream();
} catch (IOException e) {
* charset, this will attempt to decode the response body as UTF-8.
*/
@Override
- public Reader getContentReader() {
+ public Reader contentReader() {
try {
return okResponse.body().charStream();
} catch (IOException e) {
}
@Override
- public String getContent() {
+ public String content() {
try {
return okResponse.body().string();
} catch (IOException e) {
}
private RuntimeException fail(Exception e) {
- throw new IllegalStateException("Fail to read response of " + getRequestUrl(), e);
+ throw new IllegalStateException("Fail to read response of " + requestUrl(), e);
}
}
package org.sonarqube.ws.client;
-import org.sonarqube.ws.client.ce.ComputeEngineService;
import org.sonarqube.ws.client.component.ComponentsService;
import org.sonarqube.ws.client.issue.IssuesService;
import org.sonarqube.ws.client.permission.PermissionsService;
*/
public class HttpWsClient implements WsClient {
- private final ComputeEngineService ceWsClient;
private final PermissionsService permissionsService;
private final ComponentsService componentsService;
private final QualityProfilesService qualityProfilesService;
public HttpWsClient(WsConnector wsConnector) {
this.wsConnector = wsConnector;
- this.ceWsClient = new ComputeEngineService(wsConnector);
this.permissionsService = new PermissionsService(wsConnector);
this.componentsService = new ComponentsService(wsConnector);
this.qualityProfilesService = new QualityProfilesService(wsConnector);
return this.permissionsService;
}
- @Override
- public ComputeEngineService computeEngine() {
- return ceWsClient;
- }
-
@Override
public ComponentsService components() {
return componentsService;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
+import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.sonarqube.ws.MediaTypes;
import static java.util.Objects.requireNonNull;
-public class MockWsResponse implements WsResponse {
+public class MockWsResponse extends BaseResponse {
+ private int code = HttpURLConnection.HTTP_OK;
private String requestUrl;
private byte[] content;
private String contentType;
@Override
- public String getContentType() {
+ public int code() {
+ return code;
+ }
+
+ public MockWsResponse setCode(int code) {
+ this.code = code;
+ return this;
+ }
+
+ @Override
+ public String contentType() {
requireNonNull(contentType);
return contentType;
}
}
@Override
- public String getRequestUrl() {
+ public String requestUrl() {
requireNonNull(requestUrl);
return requestUrl;
}
@Override
- public InputStream getContentStream() {
+ public InputStream contentStream() {
requireNonNull(content);
return new ByteArrayInputStream(content);
}
@Override
- public Reader getContentReader() {
+ public Reader contentReader() {
requireNonNull(content);
return new StringReader(new String(content, StandardCharsets.UTF_8));
}
@Override
- public String getContent() {
+ public String content() {
requireNonNull(content);
return new String(content, StandardCharsets.UTF_8);
}
*/
package org.sonarqube.ws.client;
-import org.sonarqube.ws.client.ce.ComputeEngineService;
import org.sonarqube.ws.client.component.ComponentsService;
import org.sonarqube.ws.client.issue.IssuesService;
import org.sonarqube.ws.client.permission.PermissionsService;
public interface WsClient {
ComponentsService components();
- ComputeEngineService computeEngine();
-
IssuesService issues();
PermissionsService permissions();
*/
public interface WsConnector {
+ /**
+ * Server base URL, always with trailing slash, for instance "http://localhost:9000/"
+ */
+ String baseUrl();
+
/**
* @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)
*/
WsResponse call(WsRequest wsRequest);
- /**
- * Server base URL, always with trailing slash, for instance "http://localhost:9000/"
- */
- String baseUrl();
-
}
*/
public interface WsResponse {
- boolean hasContent();
+ /**
+ * The absolute requested URL
+ */
+ String requestUrl();
+
+ /**
+ * HTTP status code
+ */
+ int code();
+
+ /**
+ * Returns true if the code is in [200..300), which means the request was
+ * successfully received, understood, and accepted.
+ */
+ boolean isSuccessful() ;
- String getContentType();
+ /**
+ * Throws a {@link HttpException} if {@link #isSuccessful()} is false.
+ */
+ WsResponse failIfNotSuccessful();
+
+ String contentType();
+
+ boolean hasContent();
- String getRequestUrl();
+ InputStream contentStream();
- InputStream getContentStream();
+ Reader contentReader();
- Reader getContentReader();
+ String content();
- String getContent();
}
+++ /dev/null
-/*
- * 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.sonarqube.ws.client.ce;
-
-import org.sonarqube.ws.MediaTypes;
-import org.sonarqube.ws.WsCe;
-import org.sonarqube.ws.client.BaseService;
-import org.sonarqube.ws.client.PostRequest;
-import org.sonarqube.ws.client.WsConnector;
-
-public class ComputeEngineService extends BaseService {
-
- public ComputeEngineService(WsConnector wsConnector) {
- super(wsConnector, "api/ce");
- }
-
- public WsCe.SubmitResponse submit(SubmitWsRequest request) {
- PostRequest.Part filePart = new PostRequest.Part(MediaTypes.ZIP, request.getReport());
- PostRequest post = new PostRequest(path("submit"))
- .setParam("projectKey", request.getProjectKey())
- .setParam("projectName", request.getProjectName())
- .setParam("projectBranch", request.getProjectBranch())
- .setPart("report", filePart);
- return call(post, WsCe.SubmitResponse.parser());
- }
-}
+++ /dev/null
-/*
- * 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.sonarqube.ws.client.ce;
-
-import java.io.File;
-import javax.annotation.CheckForNull;
-
-public class SubmitWsRequest {
-
- private String projectKey;
- private String projectName;
- private String projectBranch;
- private File report;
-
- public String getProjectKey() {
- return projectKey;
- }
-
- public SubmitWsRequest setProjectKey(String projectKey) {
- this.projectKey = projectKey;
- return this;
- }
-
- @CheckForNull
- public String getProjectName() {
- return projectName;
- }
-
- public SubmitWsRequest setProjectName(String projectName) {
- this.projectName = projectName;
- return this;
- }
-
- @CheckForNull
- public String getProjectBranch() {
- return projectBranch;
- }
-
- public SubmitWsRequest setProjectBranch(String projectBranch) {
- this.projectBranch = projectBranch;
- return this;
- }
-
- @CheckForNull
- public File getReport() {
- return report;
- }
-
- public SubmitWsRequest setReport(File report) {
- this.report = report;
- return this;
- }
-}
+++ /dev/null
-/*
- * 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.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonarqube.ws.client.ce;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
WsResponse response = call(get);
- assertThat(response.getContent()).isEqualTo("ok");
+ assertThat(response.content()).isEqualTo("ok");
}
}.test();
}.test();
}
+ @Test
+ public void fail_if_http_error() {
+ new BaseService(wsConnector, "api/issues") {
+
+ public void test() {
+ GetRequest get = new GetRequest(path("issue")).setParam("key", "ABC");
+ when(wsConnector.call(get)).thenReturn(new MockWsResponse().setCode(403).setRequestUrl("https://local/foo"));
+
+ try {
+ call(get, Testing.Fake.parser());
+ fail();
+ } catch (HttpException e) {
+ assertThat(e.code()).isEqualTo(403);
+ }
+ }
+
+ }.test();
+ }
+
@Test
public void fail_to_parse_protobuf_response() {
new BaseService(wsConnector, "api/issues") {
*/
package org.sonarqube.ws.client;
-import com.squareup.okhttp.Interceptor;
-import com.squareup.okhttp.Response;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import java.io.File;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
// verify response
assertThat(response.hasContent()).isTrue();
- assertThat(response.getContent()).isEqualTo("hello, world!");
+ assertThat(response.content()).isEqualTo("hello, world!");
// verify the request received by server
RecordedRequest recordedRequest = server.takeRequest();
// verify response
assertThat(response.hasContent()).isTrue();
- assertThat(response.getContent()).isEqualTo("hello, world!");
+ assertThat(response.content()).isEqualTo("hello, world!");
// verify the request received by server
RecordedRequest recordedRequest = server.takeRequest();
PostRequest request = new PostRequest("api/issues/search");
HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
- try {
- underTest.call(request);
- fail();
- } catch (HttpException e) {
- assertThat(e.code()).isEqualTo(404);
-
- }
- }
-
- @Test
- public void intercept_request_and_response() {
- final AtomicBoolean called = new AtomicBoolean(false);
- Interceptor interceptor = new Interceptor() {
- @Override
- public Response intercept(Chain chain) throws IOException {
- called.set(true);
- return chain.proceed(chain.request());
- }
- };
-
- answerHelloWorld();
- HttpConnector underTest = new HttpConnector.Builder()
- .url(serverUrl)
- .interceptor(interceptor)
- .build();
- underTest.call(new GetRequest(""));
-
- assertThat(called.get()).isTrue();
+ WsResponse wsResponse = underTest.call(request);
+ assertThat(wsResponse.code()).isEqualTo(404);
}
@Test
GetRequest request = new GetRequest("api/issues/search");
answerHelloWorld();
- assertThat(underTest.call(request).getRequestUrl()).isEqualTo(serverUrl + "sonar/api/issues/search");
+ assertThat(underTest.call(request).requestUrl()).isEqualTo(serverUrl + "sonar/api/issues/search");
request = new GetRequest("/api/issues/search");
answerHelloWorld();
- assertThat(underTest.call(request).getRequestUrl()).isEqualTo(serverUrl + "sonar/api/issues/search");
+ assertThat(underTest.call(request).requestUrl()).isEqualTo(serverUrl + "sonar/api/issues/search");
}
private void answerHelloWorld() {
public class HttpExceptionTest {
@Test
public void test_exception() throws Exception {
- HttpException exception = new HttpException("http://localhost:9000/api/search", 500, "Not found");
+ HttpException exception = new HttpException("http://localhost:9000/api/search", 500);
assertThat(exception.code()).isEqualTo(500);
assertThat(exception.url()).isEqualTo("http://localhost:9000/api/search");
- assertThat(exception.getMessage()).isEqualTo("Error 500 on http://localhost:9000/api/search : Not found");
+ assertThat(exception.getMessage()).isEqualTo("Error 500 on http://localhost:9000/api/search");
}
}