summaryrefslogtreecommitdiffstats
path: root/sonar-ws
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-04-06 09:57:19 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-04-07 12:12:32 +0200
commita2be8c1b0c660f10b2e86ac046af3cfaea61214d (patch)
treea21057b61d9fb834c5c751e6f88021632d7fbcc3 /sonar-ws
parentf6bfd1d2f0373da2d2929d9217721a81fc3afe5d (diff)
downloadsonarqube-a2be8c1b0c660f10b2e86ac046af3cfaea61214d.tar.gz
sonarqube-a2be8c1b0c660f10b2e86ac046af3cfaea61214d.zip
SONAR-6948 Ability for Java server extensions to call web services
Diffstat (limited to 'sonar-ws')
-rw-r--r--sonar-ws/pom.xml6
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java6
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/BaseService.java4
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java (renamed from sonar-ws/src/main/java/org/sonarqube/ws/client/HttpWsClient.java)7
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java18
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsClientFactory.java30
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java132
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java (renamed from sonar-ws/src/main/java/org/sonarqube/ws/client/HttpResponse.java)11
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java15
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactories.java71
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactory.java31
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java30
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/LocalWsConnectorTest.java150
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/WsClientFactoriesTest.java47
14 files changed, 528 insertions, 30 deletions
diff --git a/sonar-ws/pom.xml b/sonar-ws/pom.xml
index 9b5cc87d130..e6a19ead6ba 100644
--- a/sonar-ws/pom.xml
+++ b/sonar-ws/pom.xml
@@ -39,6 +39,12 @@
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.sonarsource.sonarqube</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
<!-- Tests -->
<dependency>
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java
index 83c7163e384..2cfcd7448a5 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java
@@ -19,6 +19,8 @@
*/
package org.sonarqube.ws.client;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+
abstract class BaseResponse implements WsResponse {
@Override
@@ -34,4 +36,8 @@ abstract class BaseResponse implements WsResponse {
return this;
}
+ @Override
+ public boolean hasContent() {
+ return code() != HTTP_NO_CONTENT;
+ }
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseService.java
index aa5abe9b0a8..8d65ec983bb 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseService.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseService.java
@@ -26,6 +26,7 @@ import java.io.InputStream;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import org.apache.commons.io.IOUtils;
import org.sonarqube.ws.MediaTypes;
import static com.google.common.base.Preconditions.checkArgument;
@@ -56,8 +57,9 @@ public abstract class BaseService {
public <T extends Message> T convert(WsResponse response, Parser<T> parser) {
try (InputStream byteStream = response.contentStream()) {
+ byte[] bytes = IOUtils.toByteArray(byteStream);
// HTTP header "Content-Type" is not verified. It may be different than protobuf.
- return parser.parseFrom(byteStream);
+ return parser.parseFrom(bytes);
} catch (Exception e) {
throw new IllegalStateException("Fail to parse protobuf response of " + response.requestUrl(), e);
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpWsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java
index 5ceb0b6f27f..1c0d8278ee9 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpWsClient.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java
@@ -31,11 +31,12 @@ import org.sonarqube.ws.client.system.SystemService;
import org.sonarqube.ws.client.usertoken.UserTokensService;
/**
- * Entry point of the Java Client for SonarQube Web Services
+ * This class is not public anymore since version 5.5. It is
+ * created by {@link WsClientFactory}
*
* @since 5.3
*/
-public class HttpWsClient implements WsClient {
+class DefaultWsClient implements WsClient {
private final WsConnector wsConnector;
private final PermissionsService permissionsService;
@@ -49,7 +50,7 @@ public class HttpWsClient implements WsClient {
private final CeService ceService;
private final RulesService rulesService;
- public HttpWsClient(WsConnector wsConnector) {
+ DefaultWsClient(WsConnector wsConnector) {
this.wsConnector = wsConnector;
this.permissionsService = new PermissionsService(wsConnector);
this.componentsService = new ComponentsService(wsConnector);
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
index 4c0917f751c..f66bcd6330c 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
@@ -202,16 +202,23 @@ public class HttpConnector implements WsConnector {
return okHttpRequestBuilder;
}
- private HttpResponse doCall(Request okRequest) {
+ private OkHttpResponse doCall(Request okRequest) {
Call call = okHttpClient.newCall(okRequest);
try {
Response okResponse = call.execute();
- return new HttpResponse(okResponse);
+ return new OkHttpResponse(okResponse);
} catch (IOException e) {
throw new IllegalStateException("Fail to request " + okRequest.urlString(), e);
}
}
+ /**
+ * @since 5.5
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
public static class Builder {
private String url;
private String userAgent;
@@ -224,6 +231,13 @@ public class HttpConnector implements WsConnector {
private int readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLISECONDS;
/**
+ * Private since 5.5.
+ * @see HttpConnector#newBuilder()
+ */
+ private Builder() {
+ }
+
+ /**
* Optional User Agent
*/
public Builder userAgent(@Nullable String userAgent) {
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsClientFactory.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsClientFactory.java
new file mode 100644
index 00000000000..227ea094104
--- /dev/null
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsClientFactory.java
@@ -0,0 +1,30 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client;
+
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.server.ws.LocalConnector;
+
+@ServerSide
+public interface LocalWsClientFactory extends WsClientFactory {
+
+ WsClient newClient(LocalConnector localConnector);
+
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java
new file mode 100644
index 00000000000..3b7af43aa88
--- /dev/null
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java
@@ -0,0 +1,132 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import org.sonar.api.server.ws.LocalConnector;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+class LocalWsConnector implements WsConnector {
+
+ private final LocalConnector localConnector;
+
+ LocalWsConnector(LocalConnector localConnector) {
+ this.localConnector = localConnector;
+ }
+
+ @VisibleForTesting
+ LocalConnector getLocalConnector() {
+ return localConnector;
+ }
+
+ @Override
+ public String baseUrl() {
+ return "/";
+ }
+
+ @Override
+ public WsResponse call(WsRequest wsRequest) {
+ DefaultLocalRequest localRequest = new DefaultLocalRequest(wsRequest);
+ LocalConnector.LocalResponse localResponse = localConnector.call(localRequest);
+ return new ByteArrayResponse(wsRequest.getPath(), localResponse);
+ }
+
+ private static class DefaultLocalRequest implements LocalConnector.LocalRequest {
+ private final WsRequest wsRequest;
+
+ public DefaultLocalRequest(WsRequest wsRequest) {
+ this.wsRequest = wsRequest;
+ }
+
+ @Override
+ public String getPath() {
+ return wsRequest.getPath();
+ }
+
+ @Override
+ public String getMediaType() {
+ return wsRequest.getMediaType();
+ }
+
+ @Override
+ public String getMethod() {
+ return wsRequest.getMethod().name();
+ }
+
+ @Override
+ public boolean hasParam(String key) {
+ return wsRequest.getParams().containsKey(key);
+ }
+
+ @Override
+ public String getParam(String key) {
+ return wsRequest.getParams().get(key);
+ }
+ }
+
+ private static class ByteArrayResponse extends BaseResponse {
+ private final String path;
+ private final byte[] bytes;
+ private final String contentType;
+ private final int code;
+
+ ByteArrayResponse(String path, LocalConnector.LocalResponse localResponse) {
+ this.path = path;
+ this.bytes = localResponse.getBytes();
+ this.contentType = localResponse.getMediaType();
+ this.code = localResponse.getStatus();
+ }
+
+ @Override
+ public String requestUrl() {
+ return path;
+ }
+
+ @Override
+ public int code() {
+ return code;
+ }
+
+ @Override
+ public String contentType() {
+ return contentType;
+ }
+
+ @Override
+ public InputStream contentStream() {
+ return new ByteArrayInputStream(bytes);
+ }
+
+ @Override
+ public Reader contentReader() {
+ return new InputStreamReader(new ByteArrayInputStream(bytes), UTF_8);
+ }
+
+ @Override
+ public String content() {
+ return new String(bytes, UTF_8);
+ }
+ }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpResponse.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java
index b770424728a..30217f16681 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpResponse.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java
@@ -24,13 +24,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
-import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
-
-class HttpResponse extends BaseResponse {
+class OkHttpResponse extends BaseResponse {
private final Response okResponse;
- HttpResponse(Response okResponse) {
+ OkHttpResponse(Response okResponse) {
this.okResponse = okResponse;
}
@@ -45,11 +43,6 @@ class HttpResponse extends BaseResponse {
}
@Override
- public boolean hasContent() {
- return okResponse.code() != HTTP_NO_CONTENT;
- }
-
- @Override
public String contentType() {
return okResponse.header("Content-Type");
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java
index 522e6054a46..fc79d58e695 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java
@@ -31,6 +31,21 @@ import org.sonarqube.ws.client.system.SystemService;
import org.sonarqube.ws.client.usertoken.UserTokensService;
/**
+ * Allows to request the web services of SonarQube server. Instance is provided by
+ * {@link WsClientFactory}.
+ *
+ * <p>
+ * Usage:
+ * <pre>
+ * HttpConnector httpConnector = HttpConnector.newBuilder()
+ * .url("http://localhost:9000")
+ * .credentials("admin", "admin")
+ * .build();
+ * WsClient wsClient = WsClientFactories.getDefault().newClient(httpConnector);
+ * wsClient.issues().search(issueRequest);
+ * </pre>
+ * </p>
+ *
* @since 5.3
*/
public interface WsClient {
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactories.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactories.java
new file mode 100644
index 00000000000..1f0898f95e3
--- /dev/null
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactories.java
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client;
+
+import org.sonar.api.server.ws.LocalConnector;
+
+/**
+ * All provided implementations of {@link WsClientFactory}.
+ */
+public class WsClientFactories {
+
+ private WsClientFactories() {
+ // prevent instantiation
+ }
+
+ /**
+ * Factory to be used when connecting to a remote SonarQube web server.
+ */
+ public static WsClientFactory getDefault() {
+ return DefaultWsClientFactory.INSTANCE;
+ }
+
+ /**
+ * Factory that allows a SonarQube web service to interact
+ * with other web services, without using the HTTP stack.
+ * @see org.sonar.api.server.ws.LocalConnector
+ */
+ public static LocalWsClientFactory getLocal() {
+ return DefaultLocalWsClientFactory.INSTANCE;
+ }
+
+ private enum DefaultWsClientFactory implements WsClientFactory {
+ INSTANCE;
+
+ @Override
+ public WsClient newClient(WsConnector connector) {
+ return new DefaultWsClient(connector);
+ }
+ }
+
+ private enum DefaultLocalWsClientFactory implements LocalWsClientFactory {
+ INSTANCE;
+
+ @Override
+ public WsClient newClient(WsConnector connector) {
+ return DefaultWsClientFactory.INSTANCE.newClient(connector);
+ }
+
+ @Override
+ public WsClient newClient(LocalConnector localConnector) {
+ return new DefaultWsClient(new LocalWsConnector(localConnector));
+ }
+ }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactory.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactory.java
new file mode 100644
index 00000000000..d7a89c2e742
--- /dev/null
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClientFactory.java
@@ -0,0 +1,31 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client;
+
+/**
+ * Creates {@link WsClient}. Implementations are provided by {@link WsClientFactories}.
+ *
+ * @since 5.5
+ */
+public interface WsClientFactory {
+
+ WsClient newClient(WsConnector connector);
+
+}
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java
index a18407bd28b..767978108a7 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java
@@ -60,7 +60,7 @@ public class HttpConnectorTest {
@Test
public void test_default_settings() throws Exception {
answerHelloWorld();
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl).build();
assertThat(underTest.baseUrl()).isEqualTo(serverUrl);
GetRequest request = new GetRequest("api/issues/search").setMediaType(MediaTypes.PROTOBUF);
WsResponse response = underTest.call(request);
@@ -87,7 +87,7 @@ public class HttpConnectorTest {
@Test
public void use_basic_authentication() throws Exception {
answerHelloWorld();
- HttpConnector underTest = new HttpConnector.Builder()
+ HttpConnector underTest = HttpConnector.newBuilder()
.url(serverUrl)
.credentials("theLogin", "thePassword")
.build();
@@ -102,7 +102,7 @@ public class HttpConnectorTest {
@Test
public void use_basic_authentication_with_null_password() throws Exception {
answerHelloWorld();
- HttpConnector underTest = new HttpConnector.Builder()
+ HttpConnector underTest = HttpConnector.newBuilder()
.url(serverUrl)
.credentials("theLogin", null)
.build();
@@ -121,7 +121,7 @@ public class HttpConnectorTest {
@Test
public void use_access_token() throws Exception {
answerHelloWorld();
- HttpConnector underTest = new HttpConnector.Builder()
+ HttpConnector underTest = HttpConnector.newBuilder()
.url(serverUrl)
.token("theToken")
.build();
@@ -136,7 +136,7 @@ public class HttpConnectorTest {
@Test
public void use_proxy_authentication() throws Exception {
answerHelloWorld();
- HttpConnector underTest = new HttpConnector.Builder()
+ HttpConnector underTest = HttpConnector.newBuilder()
.url(serverUrl)
.proxyCredentials("theProxyLogin", "theProxyPassword")
.build();
@@ -150,7 +150,7 @@ public class HttpConnectorTest {
@Test
public void override_timeouts() {
- HttpConnector underTest = new HttpConnector.Builder()
+ HttpConnector underTest = HttpConnector.newBuilder()
.url(serverUrl)
.readTimeoutMilliseconds(42)
.connectTimeoutMilliseconds(74)
@@ -163,7 +163,7 @@ public class HttpConnectorTest {
@Test
public void send_user_agent() throws Exception {
answerHelloWorld();
- HttpConnector underTest = new HttpConnector.Builder()
+ HttpConnector underTest = HttpConnector.newBuilder()
.url(serverUrl)
.userAgent("Maven Plugin/2.3")
.build();
@@ -176,7 +176,7 @@ public class HttpConnectorTest {
@Test
public void fail_if_unknown_implementation_of_request() {
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl).build();
try {
underTest.call(mock(WsRequest.class));
fail();
@@ -192,7 +192,7 @@ public class HttpConnectorTest {
.setParam("severity", "MAJOR")
.setMediaType(MediaTypes.PROTOBUF);
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl).build();
WsResponse response = underTest.call(request);
// verify response
@@ -215,7 +215,7 @@ public class HttpConnectorTest {
.setPart("report", new PostRequest.Part(MediaTypes.TXT, reportFile))
.setMediaType(MediaTypes.PROTOBUF);
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl).build();
WsResponse response = underTest.call(request);
assertThat(response.hasContent()).isTrue();
@@ -233,7 +233,7 @@ public class HttpConnectorTest {
public void http_error() throws Exception {
server.enqueue(new MockResponse().setResponseCode(404));
PostRequest request = new PostRequest("api/issues/search");
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl).build();
WsResponse wsResponse = underTest.call(request);
assertThat(wsResponse.code()).isEqualTo(404);
@@ -242,7 +242,7 @@ public class HttpConnectorTest {
@Test
public void support_base_url_ending_with_slash() throws Exception {
assertThat(serverUrl).endsWith("/");
- HttpConnector underTest = new HttpConnector.Builder().url(StringUtils.removeEnd(serverUrl, "/")).build();
+ HttpConnector underTest = HttpConnector.newBuilder().url(StringUtils.removeEnd(serverUrl, "/")).build();
GetRequest request = new GetRequest("api/issues/search");
answerHelloWorld();
@@ -255,7 +255,7 @@ public class HttpConnectorTest {
public void support_base_url_with_context() {
// just to be sure
assertThat(serverUrl).endsWith("/");
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl + "sonar").build();
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl + "sonar").build();
GetRequest request = new GetRequest("api/issues/search");
answerHelloWorld();
@@ -269,7 +269,7 @@ public class HttpConnectorTest {
@Test
public void support_tls_1_2_on_java7() {
when(javaVersion.isJava7()).thenReturn(true);
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build(javaVersion);
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl).build(javaVersion);
assertTlsAndClearTextSpecifications(underTest);
// enable TLS 1.0, 1.1 and 1.2
@@ -279,7 +279,7 @@ public class HttpConnectorTest {
@Test
public void support_tls_versions_of_java8() {
when(javaVersion.isJava7()).thenReturn(false);
- HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build(javaVersion);
+ HttpConnector underTest = HttpConnector.newBuilder().url(serverUrl).build(javaVersion);
assertTlsAndClearTextSpecifications(underTest);
assertThat(underTest.okHttpClient().getSslSocketFactory()).isInstanceOf(SSLSocketFactory.getDefault().getClass());
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/LocalWsConnectorTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/LocalWsConnectorTest.java
new file mode 100644
index 00000000000..d92f4a8d3d5
--- /dev/null
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/LocalWsConnectorTest.java
@@ -0,0 +1,150 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.io.IOUtils;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Test;
+import org.sonar.api.server.ws.LocalConnector;
+import org.sonarqube.ws.MediaTypes;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class LocalWsConnectorTest {
+
+ LocalConnector connector = mock(LocalConnector.class);
+ LocalWsConnector underTest = new LocalWsConnector(connector);
+
+ @Test
+ public void baseUrl_is_always_slash() {
+ assertThat(underTest.baseUrl()).isEqualTo("/");
+ }
+
+ @Test
+ public void call_request() throws Exception {
+ WsRequest wsRequest = new PostRequest("api/issues/search")
+ .setMediaType(MediaTypes.JSON)
+ .setParam("foo", "bar");
+ answer(new DumbLocalResponse(400, MediaTypes.JSON, "{}".getBytes(UTF_8), Collections.<String>emptyList()));
+
+ WsResponse wsResponse = underTest.call(wsRequest);
+
+ verifyRequested("POST", "api/issues/search", MediaTypes.JSON, ImmutableMap.of("foo", "bar"));
+ assertThat(wsResponse.code()).isEqualTo(400);
+ assertThat(wsResponse.content()).isEqualTo("{}");
+ assertThat(IOUtils.toString(wsResponse.contentReader())).isEqualTo("{}");
+ assertThat(IOUtils.toString(wsResponse.contentStream())).isEqualTo("{}");
+ assertThat(wsResponse.contentType()).isEqualTo(MediaTypes.JSON);
+ assertThat(wsResponse.requestUrl()).isEqualTo("api/issues/search");
+ }
+
+ @Test
+ public void call_request_with_defaults() throws Exception {
+ // no parameters, no media type
+ WsRequest wsRequest = new GetRequest("api/issues/search");
+ answer(new DumbLocalResponse(200, MediaTypes.JSON, "".getBytes(UTF_8), Collections.<String>emptyList()));
+
+ WsResponse wsResponse = underTest.call(wsRequest);
+
+ verifyRequested("GET", "api/issues/search", MediaTypes.JSON, Collections.<String, String>emptyMap());
+ assertThat(wsResponse.code()).isEqualTo(200);
+ assertThat(wsResponse.content()).isEqualTo("");
+ assertThat(IOUtils.toString(wsResponse.contentReader())).isEqualTo("");
+ assertThat(IOUtils.toString(wsResponse.contentStream())).isEqualTo("");
+ assertThat(wsResponse.contentType()).isEqualTo(MediaTypes.JSON);
+ }
+
+ private void answer(DumbLocalResponse response) {
+ when(connector.call(any(LocalConnector.LocalRequest.class))).thenReturn(response);
+ }
+
+ private void verifyRequested(final String expectedMethod, final String expectedPath,
+ final String expectedMediaType,
+ final Map<String, String> expectedParams) {
+ verify(connector).call(argThat(new TypeSafeMatcher<LocalConnector.LocalRequest>() {
+ @Override
+ protected boolean matchesSafely(LocalConnector.LocalRequest localRequest) {
+ boolean ok = localRequest.getMethod().equals(expectedMethod) && localRequest.getPath().equals(expectedPath);
+ ok &= localRequest.getMediaType().equals(expectedMediaType);
+ for (Map.Entry<String, String> expectedParam : expectedParams.entrySet()) {
+ String paramKey = expectedParam.getKey();
+ ok &= localRequest.hasParam(paramKey);
+ ok &= expectedParam.getValue().equals(localRequest.getParam(paramKey));
+ }
+ return ok;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ }
+ }));
+ }
+
+ private static class DumbLocalResponse implements LocalConnector.LocalResponse {
+ private final int code;
+ private final String mediaType;
+ private final byte[] bytes;
+ private final List<String> headers;
+
+ public DumbLocalResponse(int code, String mediaType, byte[] bytes, List<String> headers) {
+ this.code = code;
+ this.mediaType = mediaType;
+ this.bytes = bytes;
+ this.headers = headers;
+ }
+
+ @Override
+ public int getStatus() {
+ return code;
+ }
+
+ @Override
+ public String getMediaType() {
+ return mediaType;
+ }
+
+ @Override
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ @Override
+ public Collection<String> getHeaderNames() {
+ return headers;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/WsClientFactoriesTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/WsClientFactoriesTest.java
new file mode 100644
index 00000000000..351a80dc295
--- /dev/null
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/WsClientFactoriesTest.java
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.LocalConnector;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class WsClientFactoriesTest {
+ @Test
+ public void create_http_client() {
+ HttpConnector connector = HttpConnector.newBuilder().url("http://localhost:9000").build();
+ WsClient client = WsClientFactories.getDefault().newClient(connector);
+
+ assertThat(client).isInstanceOf(DefaultWsClient.class);
+ assertThat(client.wsConnector()).isSameAs(connector);
+ }
+
+ @Test
+ public void create_local_client() {
+ LocalConnector connector = mock(LocalConnector.class);
+ WsClient client = WsClientFactories.getLocal().newClient(connector);
+
+ assertThat(client).isInstanceOf(DefaultWsClient.class);
+ assertThat(client.wsConnector()).isInstanceOf(LocalWsConnector.class);
+ assertThat(((LocalWsConnector) client.wsConnector()).getLocalConnector()).isSameAs(connector);
+ }
+}