Skip to content

Commit

Permalink
SONAR-6947 New WsClient
Browse files Browse the repository at this point in the history
  • Loading branch information
teryk committed Nov 17, 2015
1 parent e754b60 commit a3aa150
Show file tree
Hide file tree
Showing 9 changed files with 381 additions and 182 deletions.
160 changes: 160 additions & 0 deletions sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
@@ -0,0 +1,160 @@
/*
* 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;

import com.google.protobuf.Message;
import com.google.protobuf.Parser;
import javax.annotation.Nullable;

public class HttpConnector implements WsConnector {

public static final int DEFAULT_CONNECT_TIMEOUT_MILLISECONDS = 30000;
public static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60000;

/**
* Visibility relaxed for unit tests
*/
final HttpRequestFactory requestFactory;

private HttpConnector(Builder builder) {
this.requestFactory = new HttpRequestFactory(builder.url)
.setLogin(builder.login)
.setPassword(builder.password)
.setProxyHost(builder.proxyHost)
.setProxyPort(builder.proxyPort)
.setProxyLogin(builder.proxyLogin)
.setProxyPassword(builder.proxyPassword)
.setConnectTimeoutInMilliseconds(builder.connectTimeoutMs)
.setReadTimeoutInMilliseconds(builder.readTimeoutMs);
}

@Override
public String execute(WsRequest wsRequest) {
return requestFactory.execute(wsRequest);
}

@Override
public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) {
return requestFactory.execute(wsRequest, protobufParser);
}

/**
* Create a builder of {@link WsClient}s.
*/
public static Builder newHttpConnector() {
return new Builder();
}

/**
* Create a client with default configuration. Use {@link #newHttpConnector()} to define
* a custom configuration (credentials, HTTP proxy, HTTP timeouts).
*/
public static HttpConnector newDefaultHttpConnector(String serverUrl) {
return newHttpConnector().url(serverUrl).build();
}

public static class Builder {
private String login;
private String password;
private String url;
private String proxyHost;
private String proxyLogin;
private String proxyPassword;
private int proxyPort = 0;

private int connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MILLISECONDS, readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLISECONDS;

private Builder() {
}

/**
* Mandatory HTTP server URL, eg "http://localhost:9000"
*/
public Builder url(String url) {
this.url = url;
return this;
}

/**
* Optional login, for example "admin"
*/
public Builder login(@Nullable String login) {
this.login = login;
return this;
}

/**
* Optional password related to {@link #login(String)}, for example "admin"
*/
public Builder password(@Nullable String password) {
this.password = password;
return this;
}

/**
* Host and port of the optional HTTP proxy
*/
public Builder proxy(@Nullable String proxyHost, int proxyPort) {
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
return this;
}

public Builder proxyLogin(@Nullable String proxyLogin) {
this.proxyLogin = proxyLogin;
return this;
}

public Builder proxyPassword(@Nullable String proxyPassword) {
this.proxyPassword = proxyPassword;
return this;
}

/**
* Sets a specified timeout value, in milliseconds, to be used when opening HTTP connection.
* A timeout of zero is interpreted as an infinite timeout. Default value is {@link HttpConnector#DEFAULT_CONNECT_TIMEOUT_MILLISECONDS}
*/
public Builder connectTimeoutMilliseconds(int i) {
this.connectTimeoutMs = i;
return this;
}

/**
* Sets the read timeout to a specified timeout, in milliseconds.
* A timeout of zero is interpreted as an infinite timeout. Default value is {@link HttpConnector#DEFAULT_READ_TIMEOUT_MILLISECONDS}
*/
public Builder readTimeoutMilliseconds(int i) {
this.readTimeoutMs = i;
return this;
}

/**
* Build a new client
*/
public HttpConnector build() {
if (url == null || "".equals(url)) {
throw new IllegalStateException("Server URL must be set");
}
return new HttpConnector(this);
}

}
}
Expand Up @@ -21,12 +21,12 @@


import com.github.kevinsawicki.http.HttpRequest; import com.github.kevinsawicki.http.HttpRequest;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.net.MediaType;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import com.google.protobuf.Parser; import com.google.protobuf.Parser;
import java.util.Arrays; import java.util.Arrays;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.sonarqube.ws.MediaTypes;


import static java.net.HttpURLConnection.HTTP_CREATED; import static java.net.HttpURLConnection.HTTP_CREATED;
import static java.net.HttpURLConnection.HTTP_NO_CONTENT; import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
Expand Down Expand Up @@ -136,8 +136,9 @@ public String execute(WsRequest wsRequest) {


public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) { public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) {
HttpRequest httpRequest = wsRequestToHttpRequest(wsRequest); HttpRequest httpRequest = wsRequestToHttpRequest(wsRequest);
String response = execute(httpRequest);
try { try {
return protobufParser.parseFrom(httpRequest.bytes()); return protobufParser.parseFrom(response.getBytes());
} catch (InvalidProtocolBufferException e) { } catch (InvalidProtocolBufferException e) {
Throwables.propagate(e); Throwables.propagate(e);
} }
Expand All @@ -147,19 +148,21 @@ public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufPars


private HttpRequest wsRequestToHttpRequest(WsRequest wsRequest) { private HttpRequest wsRequestToHttpRequest(WsRequest wsRequest) {
HttpRequest httpRequest = wsRequest.getMethod().equals(WsRequest.Method.GET) HttpRequest httpRequest = wsRequest.getMethod().equals(WsRequest.Method.GET)
? HttpRequest.post(buildUrl(wsRequest.getUrl()), wsRequest.getParams(), true) ? HttpRequest.post(buildUrl(wsRequest.getEndpoint()), wsRequest.getParams(), true)
: HttpRequest.get(buildUrl(wsRequest.getUrl()), wsRequest.getParams(), true); : HttpRequest.get(buildUrl(wsRequest.getEndpoint()), wsRequest.getParams(), true);
httpRequest = prepare(httpRequest); httpRequest = prepare(httpRequest);
switch (wsRequest.getMediaType()) { switch (wsRequest.getMediaType()) {
case PROTOBUF: case PROTOBUF:
httpRequest.accept(MediaType.PROTOBUF.toString()); httpRequest.accept(MediaTypes.PROTOBUF);
break; break;
case JSON: case JSON:
httpRequest.accept(MediaType.JSON_UTF_8.toString()); httpRequest.accept(MediaTypes.JSON);
break; break;
case TEXT: case TEXT:
httpRequest.accept(MediaTypes.TXT);
break;
default: default:
httpRequest.accept(MediaType.PLAIN_TEXT_UTF_8.toString()); httpRequest.accept(MediaTypes.DEFAULT);
break; break;
} }


Expand Down
141 changes: 15 additions & 126 deletions sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java
Expand Up @@ -20,154 +20,43 @@


package org.sonarqube.ws.client; package org.sonarqube.ws.client;


import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import com.google.protobuf.Parser; import com.google.protobuf.Parser;
import javax.annotation.Nullable; import org.sonarqube.ws.client.permission.PermissionsWsClient;

import static org.sonarqube.ws.client.WsRequest.MediaType.PROTOBUF;


/** /**
* Entry point of the Java Client for SonarQube Web Services. * Entry point of the Java Client for SonarQube Web Services.
* <p/> * <p/>
* Example: * Example:
* <pre> * <pre>
* WsClient client = WsClient.create("http://localhost:9000"); * WsClient client = new WsClient(Connector);
* </pre> * </pre>
* *
* @since 5.2 * @since 5.2
*/ */
public class WsClient { public class WsClient {


public static final int DEFAULT_CONNECT_TIMEOUT_MILLISECONDS = 30000; @VisibleForTesting
public static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60000; final WsConnector wsConnector;

private final PermissionsWsClient permissionsWsClient;
/**
* Visibility relaxed for unit tests
*/
final HttpRequestFactory requestFactory;


private WsClient(Builder builder) { public WsClient(WsConnector wsConnector) {
this(new HttpRequestFactory(builder.url) this.wsConnector = wsConnector;
.setLogin(builder.login) this.permissionsWsClient = new PermissionsWsClient(this);
.setPassword(builder.password)
.setProxyHost(builder.proxyHost)
.setProxyPort(builder.proxyPort)
.setProxyLogin(builder.proxyLogin)
.setProxyPassword(builder.proxyPassword)
.setConnectTimeoutInMilliseconds(builder.connectTimeoutMs)
.setReadTimeoutInMilliseconds(builder.readTimeoutMs));
}

/**
* Visible for testing
*/
WsClient(HttpRequestFactory requestFactory) {
this.requestFactory = requestFactory;
}

/**
* Create a builder of {@link WsClient}s.
*/
public static Builder builder() {
return new Builder();
}

/**
* Create a client with default configuration. Use {@link #builder()} to define
* a custom configuration (credentials, HTTP proxy, HTTP timeouts).
*/
public static WsClient create(String serverUrl) {
return builder().url(serverUrl).build();
} }


public String execute(WsRequest wsRequest) { public String execute(WsRequest wsRequest) {
return requestFactory.execute(wsRequest); return wsConnector.execute(wsRequest);
} }


public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) { public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) {
return requestFactory.execute(wsRequest, protobufParser); return wsConnector.execute(wsRequest.setMediaType(PROTOBUF), protobufParser);
} }


public static class Builder { public PermissionsWsClient permissionsClient() {
private String login; return this.permissionsWsClient;
private String password;
private String url;
private String proxyHost;
private String proxyLogin;
private String proxyPassword;
private int proxyPort = 0;
private int connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MILLISECONDS, readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLISECONDS;

private Builder() {
}

/**
* Mandatory HTTP server URL, eg "http://localhost:9000"
*/
public Builder url(String url) {
this.url = url;
return this;
}

/**
* Optional login, for example "admin"
*/
public Builder login(@Nullable String login) {
this.login = login;
return this;
}

/**
* Optional password related to {@link #login(String)}, for example "admin"
*/
public Builder password(@Nullable String password) {
this.password = password;
return this;
}

/**
* Host and port of the optional HTTP proxy
*/
public Builder proxy(@Nullable String proxyHost, int proxyPort) {
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
return this;
}

public Builder proxyLogin(@Nullable String proxyLogin) {
this.proxyLogin = proxyLogin;
return this;
}

public Builder proxyPassword(@Nullable String proxyPassword) {
this.proxyPassword = proxyPassword;
return this;
}

/**
* Sets a specified timeout value, in milliseconds, to be used when opening HTTP connection.
* A timeout of zero is interpreted as an infinite timeout. Default value is {@link WsClient#DEFAULT_CONNECT_TIMEOUT_MILLISECONDS}
*/
public Builder connectTimeoutMilliseconds(int i) {
this.connectTimeoutMs = i;
return this;
}

/**
* Sets the read timeout to a specified timeout, in milliseconds.
* A timeout of zero is interpreted as an infinite timeout. Default value is {@link WsClient#DEFAULT_READ_TIMEOUT_MILLISECONDS}
*/
public Builder readTimeoutMilliseconds(int i) {
this.readTimeoutMs = i;
return this;
}

/**
* Build a new client
*/
public WsClient build() {
if (url == null || "".equals(url)) {
throw new IllegalStateException("Server URL must be set");
}
return new WsClient(this);
}
} }
} }

0 comments on commit a3aa150

Please sign in to comment.