try {
// Create a user having admin permission on the project
adminClient.userClient().create(UserParameters.create().login(projectAdminUser).name(projectAdminUser).password("password").passwordConfirmation("password"));
- adminWsClient.permissionsClient().addUser(
+ adminWsClient.permissions().addUser(
new AddUserWsRequest()
.setLogin(projectAdminUser)
.setProjectKey(PROJECT_KEY)
// Create a user having browse permission on the project
adminClient.userClient().create(UserParameters.create().login(projectUser).name(projectUser).password("password").passwordConfirmation("password"));
- adminWsClient.permissionsClient().addUser(
+ adminWsClient.permissions().addUser(
new AddUserWsRequest()
.setLogin(projectUser)
.setProjectKey(PROJECT_KEY)
import org.junit.Ignore;
import org.junit.Test;
import org.sonarqube.ws.WsUserTokens;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.HttpConnector;
+import org.sonarqube.ws.client.HttpWsClient;
+import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.WsResponse;
import org.sonarqube.ws.client.permission.AddGroupWsRequest;
import org.sonarqube.ws.client.permission.AddUserWsRequest;
import org.sonarqube.ws.client.permission.RemoveGroupWsRequest;
import org.sonarqube.ws.client.usertoken.GenerateWsRequest;
-import org.sonarqube.ws.client.usertoken.UserTokensWsClient;
+import org.sonarqube.ws.client.usertoken.UserTokensService;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonarqube.ws.client.HttpConnector.newHttpConnector;
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-import static org.sonarqube.ws.client.WsRequest.newPostRequest;
import static util.ItUtils.newAdminWsClient;
import static util.ItUtils.projectDir;
@ClassRule
public static Orchestrator ORCHESTRATOR = Category1Suite.ORCHESTRATOR;
private static WsClient adminWsClient;
- private static UserTokensWsClient userTokensWsClient;
+ private static UserTokensService userTokensWsClient;
private static final String PROJECT_KEY = "sample";
private static final String LOGIN = "george.orwell";
ORCHESTRATOR.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
adminWsClient = newAdminWsClient(ORCHESTRATOR);
- userTokensWsClient = adminWsClient.userTokensWsClient();
+ userTokensWsClient = adminWsClient.userTokens();
removeGroupPermission("anyone", "dryRunScan");
removeGroupPermission("anyone", "scan");
createUser(login, name, password);
// authenticate
- WsClient wsClient = new WsClient(newHttpConnector().url(ORCHESTRATOR.getServer().getUrl()).login(login).password(password).build());
- String response = wsClient.execute(newGetRequest("api/authentication/validate"));
- assertThat(response).isEqualTo("{\"valid\":true}");
+ 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}");
}
@Test
WsUserTokens.GenerateWsResponse generateWsResponse = userTokensWsClient.generate(new GenerateWsRequest()
.setLogin(LOGIN)
.setName("Validate token based authentication"));
- WsClient wsClient = new WsClient(newHttpConnector()
+ WsClient wsClient = new HttpWsClient(new HttpConnector.Builder()
.url(ORCHESTRATOR.getServer().getUrl())
- .login(generateWsResponse.getToken())
- .password("").build());
+ .token(generateWsResponse.getToken()).build());
- String response = wsClient.execute(newGetRequest("api/authentication/validate"));
+ WsResponse response = wsClient.wsConnector().call(new GetRequest("api/authentication/validate"));
- assertThat(response).isEqualTo("{\"valid\":true}");
+ assertThat(response.getContent()).isEqualTo("{\"valid\":true}");
}
/**
createUser(login, format("name-%s", userId), password);
// authenticate
- WsClient wsClient = new WsClient(newHttpConnector().url(ORCHESTRATOR.getServer().getUrl()).login(login).password(password).build());
- String response = wsClient.execute(newGetRequest("api/authentication/validate"));
- assertThat(response).isEqualTo("{\"valid\":false}");
+ 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}");
}
@Test
}
private static void createUser(String login, String password) {
- adminWsClient.execute(
- newPostRequest("api/users/create")
+ adminWsClient.wsConnector().call(
+ new PostRequest("api/users/create")
.setParam("login", login)
.setParam("name", login)
.setParam("password", password));
}
private static void createUser(String login, String name, String password) {
- adminWsClient.execute(
- newPostRequest("api/users/create")
+ adminWsClient.wsConnector().call(
+ new PostRequest("api/users/create")
.setParam("login", login)
.setParam("name", name)
.setParam("password", password));
}
private static void addUserPermission(String login, String permission) {
- adminWsClient.permissionsClient().addUser(new AddUserWsRequest()
+ adminWsClient.permissions().addUser(new AddUserWsRequest()
.setLogin(login)
.setPermission(permission));
}
private static void deactivateUser(String login) {
- adminWsClient.execute(
- newPostRequest("api/users/deactivate")
+ adminWsClient.wsConnector().call(
+ new PostRequest("api/users/deactivate")
.setParam("login", login));
}
private static void removeGroupPermission(String groupName, String permission) {
- adminWsClient.permissionsClient().removeGroup(new RemoveGroupWsRequest()
+ adminWsClient.permissions().removeGroup(new RemoveGroupWsRequest()
.setGroupName(groupName)
.setPermission(permission));
}
private static void addGroupPermission(String groupName, String permission) {
- adminWsClient.permissionsClient().addGroup(new AddGroupWsRequest()
+ adminWsClient.permissions().addGroup(new AddGroupWsRequest()
.setGroupName(groupName)
.setPermission(permission));
}
}
private void addUserPermission(String login, String projectKey, String permission) {
- adminWsClient.permissionsClient().addUser(
+ adminWsClient.permissions().addUser(
new AddUserWsRequest()
.setLogin(login)
.setProjectKey(projectKey)
}
private void removeGroupPermission(String groupName, String projectKey, String permission) {
- adminWsClient.permissionsClient().removeGroup(new RemoveGroupWsRequest()
+ adminWsClient.permissions().removeGroup(new RemoveGroupWsRequest()
.setGroupName(groupName)
.setProjectKey(projectKey)
.setPermission(permission));
import org.junit.Test;
import org.sonarqube.ws.WsPermissions;
import org.sonarqube.ws.WsPermissions.SearchTemplatesWsResponse;
+import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.permission.AddGroupToTemplateWsRequest;
import org.sonarqube.ws.client.permission.AddGroupWsRequest;
import org.sonarqube.ws.client.permission.AddUserWsRequest;
import org.sonarqube.ws.client.permission.CreateTemplateWsRequest;
import org.sonarqube.ws.client.permission.GroupsWsRequest;
-import org.sonarqube.ws.client.permission.PermissionsWsClient;
+import org.sonarqube.ws.client.permission.PermissionsService;
import org.sonarqube.ws.client.permission.RemoveGroupFromTemplateWsRequest;
import org.sonarqube.ws.client.permission.RemoveUserFromTemplateWsRequest;
import org.sonarqube.ws.client.permission.SearchTemplatesWsRequest;
import org.sonarqube.ws.client.permission.UsersWsRequest;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonarqube.ws.client.WsRequest.newPostRequest;
import static util.ItUtils.newAdminWsClient;
import static util.ItUtils.projectDir;
@ClassRule
public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR;
private static WsClient adminWsClient;
- private static PermissionsWsClient permissionsWsClient;
+ private static PermissionsService permissionsWsClient;
private static final String PROJECT_KEY = "sample";
private static final String LOGIN = "george.orwell";
orchestrator.executeBuild(sampleProject);
adminWsClient = newAdminWsClient(orchestrator);
- permissionsWsClient = adminWsClient.permissionsClient();
+ permissionsWsClient = adminWsClient.permissions();
createUser(LOGIN, "George Orwell");
createGroup(GROUP_NAME);
}
private static void createUser(String login, String name) {
- adminWsClient.execute(
- newPostRequest("api/users/create")
+ adminWsClient.wsConnector().call(
+ new PostRequest("api/users/create")
.setParam("login", login)
.setParam("name", name)
.setParam("password", "123456"));
}
private static void deactivateUser(String login) {
- adminWsClient.execute(
- newPostRequest("api/users/deactivate")
+ adminWsClient.wsConnector().call(
+ new PostRequest("api/users/deactivate")
.setParam("login", login));
}
private static void createGroup(String groupName) {
- adminWsClient.execute(
- newPostRequest("api/user_groups/create")
+ adminWsClient.wsConnector().call(
+ new PostRequest("api/user_groups/create")
.setParam("name", groupName));
}
private static void deleteGroup(String groupName) {
- adminWsClient.execute(
- newPostRequest("api/user_groups/delete")
+ adminWsClient.wsConnector().call(
+ new PostRequest("api/user_groups/delete")
.setParam("name", groupName));
}
}
}
private List<Issue> findIssues(String componentKey, String ruleKey) {
- return adminWsClient.issuesWsClient().search(
+ return adminWsClient.issues().search(
new SearchWsRequest()
.setComponents(singletonList(componentKey))
.setRules(singletonList(ruleKey)))
client.userClient().create(userCreationParameters);
if (permission != null) {
- adminWsClient.permissionsClient().addUser(new AddUserWsRequest()
+ adminWsClient.permissions().addUser(new AddUserWsRequest()
.setLogin(login)
.setPermission(permission));
}
package util;/*
- * Copyright (C) 2009-2014 SonarSource SA
- * All rights reserved
- * mailto:contact AT sonarsource DOT com
- */
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.sonar.wsclient.issue.IssueQuery;
import org.sonar.wsclient.services.PropertyDeleteQuery;
import org.sonar.wsclient.services.PropertyUpdateQuery;
+import org.sonarqube.ws.client.HttpConnector;
+import org.sonarqube.ws.client.HttpWsClient;
import org.sonarqube.ws.client.WsClient;
import static com.google.common.collect.FluentIterable.from;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
-import static org.sonarqube.ws.client.HttpConnector.newHttpConnector;
public class ItUtils {
public static WsClient newAdminWsClient(Orchestrator orchestrator) {
Server server = orchestrator.getServer();
- return new WsClient(newHttpConnector()
+ return new HttpWsClient(new HttpConnector.Builder()
.url(server.getUrl())
- .login(server.ADMIN_LOGIN)
- .password(server.ADMIN_PASSWORD)
+ .credentials(server.ADMIN_LOGIN, server.ADMIN_PASSWORD)
.build());
}
<slf4j.version>1.7.12</slf4j.version>
<tomcat.version>8.0.18</tomcat.version>
<elasticsearch.version>1.7.2</elasticsearch.version>
+ <okhttp.version>2.6.0</okhttp.version>
<protobuf.version>3.0.0-beta-1</protobuf.version>
<protobuf.compiler>${settings.localRepository}/com/google/protobuf/protoc/${protobuf.version}/protoc-${protobuf.version}-${os.detected.classifier}.exe</protobuf.compiler>
<exists>src/main/protobuf</exists>
</file>
</activation>
- <properties>
- <sonar.exclusions>target/generated-sources/protobuf/**/*</sonar.exclusions>
- </properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
- <id>protobuf-compile</id>
+ <id>compile-protobuf-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
- <id>protobuf-compile</id>
+ <id>add-protobuf-generated-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
<exists>src/test/protobuf</exists>
</file>
</activation>
- <properties>
- <sonar.test.exclusions>target/generated-test-sources/protobuf/**/*</sonar.test.exclusions>
- </properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
- <id>protobuf-test-compile</id>
+ <id>compile-protobuf-tests</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
- <id>protobuf-test-compile</id>
+ <id>add-protobuf-generated-tests</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
// constants
}
- static final String NO_PERMISSION = "You're not authorized to execute any SonarQube analysis. Please contact your SonarQube administrator.";
+ public static final String NO_PERMISSION = "You're not authorized to execute any SonarQube analysis. Please contact your SonarQube administrator.";
+
}
import org.sonar.api.server.ws.WebService;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.ENDPOINT;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.CONTROLLER;
public class PermissionsWs implements WebService {
private final PermissionsWsAction[] actions;
@Override
public void define(Context context) {
- NewController controller = context.createController(ENDPOINT);
+ NewController controller = context.createController(CONTROLLER);
controller.setDescription("Permissions management");
controller.setSince("3.7");
import org.sonar.api.server.ws.WebService;
-import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.USER_TOKENS_ENDPOINT;
+import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.CONTROLLER;
public class UserTokensWs implements WebService {
private final UserTokensWsAction[] actions;
@Override
public void define(Context context) {
- NewController controller = context.createController(USER_TOKENS_ENDPOINT)
+ NewController controller = context.createController(CONTROLLER)
.setDescription("User token management. To enhance security, tokens can be used to take the place " +
"of user credentials in analysis configuration. A token can be revoked at any time.")
.setSince("5.3");
loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
fail();
} catch (Exception e) {
- assertThat(e).isInstanceOf(ForbiddenException.class).hasMessage("You're not authorized to execute any SonarQube analysis. Please contact your SonarQube administrator.");
+ assertThat(e).isInstanceOf(ForbiddenException.class).hasMessage(Messages.NO_PERMISSION);
}
}
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.server.permission.ws.AddGroupAction.ACTION;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.ENDPOINT;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.CONTROLLER;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_ID;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
public void fail_when_get_request() throws Exception {
expectedException.expect(ServerException.class);
- ws.newGetRequest(ENDPOINT, ACTION)
+ ws.newGetRequest(CONTROLLER, ACTION)
.setParam(PARAM_GROUP_NAME, "sonar-administrators")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
}
private WsTester.TestRequest newRequest() {
- return ws.newPostRequest(ENDPOINT, ACTION);
+ return ws.newPostRequest(CONTROLLER, ACTION);
}
private void commit() {
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.server.permission.ws.AddUserAction.ACTION;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.ENDPOINT;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.CONTROLLER;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY;
@Test
public void call_permission_service_with_right_data() throws Exception {
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key"));
commit();
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "project-uuid")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key"));
commit();
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_KEY, "project-key")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
dbClient.componentDao().insert(dbSession, newView("view-uuid").setKey("view-key"));
commit();
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "view-uuid")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
public void fail_when_project_uuid_is_unknown() throws Exception {
expectedException.expect(NotFoundException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "unknown-project-uuid")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
public void fail_when_project_permission_without_project() throws Exception {
expectedException.expect(BadRequestException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN)
.execute();
insertComponent(newFileDto(newProjectDto("project-uuid"), "file-uuid"));
commit();
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "file-uuid")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
public void fail_when_get_request() throws Exception {
expectedException.expect(ServerException.class);
- ws.newGetRequest(ENDPOINT, ACTION)
+ ws.newGetRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "george.orwell")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
public void fail_when_user_login_is_missing() throws Exception {
expectedException.expect(IllegalArgumentException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
}
public void fail_when_permission_is_missing() throws Exception {
expectedException.expect(IllegalArgumentException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "jrr.tolkien")
.execute();
}
insertComponent(newProjectDto("project-uuid").setKey("project-key"));
commit();
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "project-uuid")
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.server.permission.ws.RemoveGroupAction.ACTION;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.ENDPOINT;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.CONTROLLER;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_ID;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
public void fail_when_get_request() throws Exception {
expectedException.expect(ServerException.class);
- ws.newGetRequest(ENDPOINT, ACTION)
+ ws.newGetRequest(CONTROLLER, ACTION)
.setParam(PARAM_GROUP_NAME, "sonar-administrators")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
}
private WsTester.TestRequest newRequest() {
- return ws.newPostRequest(ENDPOINT, ACTION);
+ return ws.newPostRequest(CONTROLLER, ACTION);
}
private GroupDto insertGroup(String groupName) {
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.server.permission.ws.RemoveUserAction.ACTION;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.ENDPOINT;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.CONTROLLER;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY;
@Test
public void call_permission_service_with_right_data() throws Exception {
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
public void remove_with_project_uuid() throws Exception {
insertComponent(newProjectDto("project-uuid").setKey("project-key"));
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "project-uuid")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
public void remove_with_project_key() throws Exception {
insertComponent(newProjectDto("project-uuid").setKey("project-key"));
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_KEY, "project-key")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
public void remove_with_view_uuid() throws Exception {
insertComponent(newView("view-uuid").setKey("view-key"));
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "view-uuid")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
public void fail_when_project_does_not_exist() throws Exception {
expectedException.expect(NotFoundException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "unknown-project-uuid")
.setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN)
public void fail_when_project_permission_without_permission() throws Exception {
expectedException.expect(BadRequestException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN)
.execute();
expectedException.expect(BadRequestException.class);
insertComponent(newFileDto(newProjectDto(), "file-uuid"));
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "file-uuid")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
public void fail_when_get_request() throws Exception {
expectedException.expect(ServerException.class);
- ws.newGetRequest(ENDPOINT, ACTION)
+ ws.newGetRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "george.orwell")
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
public void fail_when_user_login_is_missing() throws Exception {
expectedException.expect(IllegalArgumentException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.execute();
}
public void fail_when_permission_is_missing() throws Exception {
expectedException.expect(IllegalArgumentException.class);
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_USER_LOGIN, "jrr.tolkien")
.execute();
}
expectedException.expectMessage("Project id or project key can be provided, not both.");
insertComponent(newProjectDto("project-uuid").setKey("project-key"));
- ws.newPostRequest(ENDPOINT, ACTION)
+ ws.newPostRequest(CONTROLLER, ACTION)
.setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
.setParam(PARAM_USER_LOGIN, "ray.bradbury")
.setParam(PARAM_PROJECT_ID, "project-uuid")
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonarsource.sonarqube</groupId>
<artifactId>sonar-batch-protocol</artifactId>
<name>SonarQube :: Batch :: Protocol</name>
-
+
<description>Classes used for communication between batch and server</description>
-
+
<properties>
<!-- Viewer is for our internal use. This is not production code and mostly generated with Eclipse GUI builder -->
- <sonar.exclusions>src/main/java/org/sonar/batch/protocol/viewer/**</sonar.exclusions>
+ <sonar.exclusions>target/generated-sources/**/*,src/main/java/org/sonar/batch/protocol/viewer/**</sonar.exclusions>
+ <sonar.test.exclusions>target/generated-test-sources/**/*</sonar.test.exclusions>
</properties>
<dependencies>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
- <dependency>
- <groupId>com.github.kevinsawicki</groupId>
- <artifactId>http-request</artifactId>
- </dependency>
<!-- For HTML Report -->
<dependency>
<groupId>org.freemarker</groupId>
<scope>test</scope>
<version>${project.version}</version>
</dependency>
-
<dependency>
<groupId>com.google.code.bean-matchers</groupId>
<artifactId>bean-matchers</artifactId>
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.AnalysisMode;
-import org.sonar.batch.bootstrap.ServerClient;
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(AnalysisProperties props, AnalysisMode mode, PersistentCache cache, ServerClient client) {
+ public WSLoader provide(AnalysisMode mode, PersistentCache cache, WsClient client) {
if (wsLoader == null) {
// recreate cache directory if needed for this analysis
cache.reconfigure();
- wsLoader = new WSLoader(getStrategy(mode), cache, client, props);
+ wsLoader = new WSLoader(getStrategy(mode), cache, client);
}
return wsLoader;
}
import com.google.common.collect.Lists;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.SonarPlugin;
import org.sonar.core.platform.RemotePlugin;
import org.sonar.core.platform.RemotePluginFile;
import org.sonar.home.cache.FileCache;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.WsResponse;
+
+import static java.lang.String.format;
/**
* Downloads the plugins installed on server and stores them in a local user cache
private final WSLoader wsLoader;
private final FileCache fileCache;
private final BatchPluginPredicate pluginPredicate;
- private final ServerClient serverClient;
+ private final WsClient wsClient;
- public BatchPluginInstaller(WSLoader wsLoader, ServerClient serverClient, FileCache fileCache, BatchPluginPredicate pluginPredicate) {
+ public BatchPluginInstaller(WSLoader wsLoader, WsClient wsClient, FileCache fileCache, BatchPluginPredicate pluginPredicate) {
this.wsLoader = wsLoader;
this.fileCache = fileCache;
this.pluginPredicate = pluginPredicate;
- this.serverClient = serverClient;
+ this.wsClient = wsClient;
}
@Override
@Override
public void download(String filename, File toFile) throws IOException {
- String url = "/deploy/plugins/" + key + "/" + filename;
+ String url = format("/deploy/plugins/%s/%s", key, filename);
if (LOG.isDebugEnabled()) {
- LOG.debug("Download {} to {}", url, toFile.getAbsolutePath());
+ LOG.debug("Download plugin {} to {}", filename, toFile);
} else {
LOG.info("Download {}", filename);
}
- serverClient.download(url, toFile);
+ WsResponse response = wsClient.wsConnector().call(new GetRequest(url));
+ try (InputStream stream = response.getContentStream()) {
+ FileUtils.copyInputStreamToFile(stream, toFile);
+ }
}
}
}
CachesManager.class,
GlobalSettings.class,
- ServerClient.class,
+ new WsClientProvider(),
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.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.Nullable;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.BatchSide;
-import org.sonar.api.utils.HttpDownloader;
-import org.sonar.api.utils.MessageException;
-import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import org.sonar.core.util.DefaultHttpDownloader;
-
-/**
- * Replace the deprecated org.sonar.batch.ServerMetadata
- * TODO extends Server when removing the deprecated org.sonar.batch.ServerMetadata
- *
- * @since 3.4
- */
-@BatchSide
-public class ServerClient {
- private static final String GET = "GET";
- private GlobalProperties props;
- private DefaultHttpDownloader.BaseHttpDownloader downloader;
-
- public ServerClient(GlobalProperties settings, EnvironmentInformation env) {
- this.props = settings;
- this.downloader = new DefaultHttpDownloader.BaseHttpDownloader(settings.properties(), env.toString());
- }
-
- public String getURL() {
- return StringUtils.removeEnd(StringUtils.defaultIfBlank(props.property("sonar.host.url"), "http://localhost:9000"), "/");
- }
-
- public URI getURI(String pathStartingWithSlash) {
- Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /: " + pathStartingWithSlash);
- String path = StringEscapeUtils.escapeHtml(pathStartingWithSlash);
- return URI.create(getURL() + path);
- }
-
- public void download(String pathStartingWithSlash, File toFile) {
- download(pathStartingWithSlash, toFile, null, null);
- }
-
- public void download(String pathStartingWithSlash, File toFile, @Nullable Integer connectTimeoutMillis, @Nullable Integer readTimeoutMillis) {
- try {
- InputStream is = load(pathStartingWithSlash, GET, false, connectTimeoutMillis, readTimeoutMillis);
- Files.copy(is, toFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
- } catch (HttpDownloader.HttpException he) {
- throw handleHttpException(he.getUri().toString(), he.getResponseCode(), he.getResponseContent(), he);
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Unable to download '%s' to: %s", pathStartingWithSlash, toFile), e);
- }
- }
-
- public String downloadString(String pathStartingWithSlash) {
- return downloadString(pathStartingWithSlash, GET, true, null);
- }
-
- public String downloadString(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException, @Nullable Integer timeoutMillis) {
- InputStream is = load(pathStartingWithSlash, requestMethod, wrapHttpException, null, timeoutMillis);
- try {
- return new String(IOUtils.toByteArray(is), "UTF-8");
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Unable to request: %s", pathStartingWithSlash), e);
- }
- }
-
- /**
- * @throws IllegalStateException on I/O error, not limited to the network connection and if HTTP response code > 400 and wrapHttpException is true
- * @throws HttpDownloader.HttpException if HTTP response code > 400 and wrapHttpException is false
- */
- public InputStream load(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException, @Nullable Integer connectTimeoutMs,
- @Nullable Integer readTimeoutMs) {
- URI uri = getURI(pathStartingWithSlash);
-
- try {
- if (Strings.isNullOrEmpty(getLogin())) {
- return downloader.newInputSupplier(uri, requestMethod, connectTimeoutMs, readTimeoutMs).getInput();
- } else {
- return downloader.newInputSupplier(uri, requestMethod, getLogin(), getPassword(), connectTimeoutMs, readTimeoutMs).getInput();
- }
- } catch (HttpDownloader.HttpException he) {
- if (wrapHttpException) {
- throw handleHttpException(he.getUri().toString(), he.getResponseCode(), he.getResponseContent(), he);
- } else {
- throw he;
- }
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Unable to request: %s", uri), e);
- }
- }
-
- public RuntimeException handleHttpException(String url, int responseCode, String responseContent, Exception he) {
- if (responseCode == 401) {
- return MessageException.of(String.format(getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD), he);
- }
- if (responseCode == 403) {
- // SONAR-4397 Details are in response content
- return MessageException.of(tryParseAsJsonError(responseContent), he);
- }
- return MessageException.of(String.format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, responseContent), he);
- }
-
- 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;
- }
- }
-
- public String getMessageWhenNotAuthorized() {
- if (Strings.isNullOrEmpty(getLogin()) && Strings.isNullOrEmpty(getPassword())) {
- return "Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties %s and %s.";
- }
- return "Not authorized. Please check the properties %s and %s.";
- }
-
- public String getLogin() {
- return props.property(CoreProperties.LOGIN);
- }
-
- public String getPassword() {
- return props.property(CoreProperties.PASSWORD);
- }
-}
--- /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.GlobalProperties;
-import org.sonar.batch.bootstrap.ServerClient;
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, ServerClient client, GlobalProperties globalProps) {
+ public WSLoader provide(PersistentCache cache, WsClient client) {
if (wsLoader == null) {
- wsLoader = new WSLoader(strategy, cache, client, globalProps);
+ wsLoader = new WSLoader(strategy, cache, client);
}
return wsLoader;
}
import java.io.IOException;
import java.io.InputStream;
+import java.io.Reader;
import java.nio.charset.StandardCharsets;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
-import org.sonar.api.utils.HttpDownloader.HttpException;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.batch.bootstrap.ServerClient;
-import org.sonar.batch.bootstrap.UserProperties;
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;
import static org.sonar.batch.cache.WSLoader.ServerStatus.UNKNOWN;
public class WSLoader {
- static final String SONAR_WS_TIMEOUT_PROPS = "sonar.ws.timeout";
private static final Logger LOG = Loggers.get(WSLoader.class);
private static final String FAIL_MSG = "Server is not accessible and data is not cached";
- private static final int CONNECT_TIMEOUT = 5_000;
- private static final int DEFAULT_READ_TIMEOUT = 60_000;
- private static final String REQUEST_METHOD = "GET";
public enum ServerStatus {
- UNKNOWN, ACCESSIBLE, NOT_ACCESSIBLE;
+ UNKNOWN, ACCESSIBLE, NOT_ACCESSIBLE
}
public enum LoadStrategy {
- SERVER_FIRST, CACHE_FIRST, SERVER_ONLY, CACHE_ONLY;
+ SERVER_FIRST, CACHE_FIRST, SERVER_ONLY, CACHE_ONLY
}
private final LoadStrategy defautLoadStrategy;
- private final ServerClient client;
+ private final WsClient client;
private final PersistentCache cache;
- private final UserProperties userProperties;
private ServerStatus serverStatus;
private DataLoader<String> stringServerLoader = new DataLoader<String>() {
@Override
public String load(String id) throws IOException {
- InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, getReadTimeout());
- String str = IOUtils.toString(is, StandardCharsets.UTF_8);
- try {
- cache.put(id, str.getBytes(StandardCharsets.UTF_8));
- } catch (IOException e) {
- throw new IllegalStateException("Error saving to WS cache", e);
+ GetRequest getRequest = new GetRequest(id);
+ try (Reader reader = client.wsConnector().call(getRequest).getContentReader()) {
+ String str = IOUtils.toString(reader);
+ try {
+ cache.put(id, str.getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new IllegalStateException("Error saving to WS cache", e);
+ }
+ return str;
}
- return str;
}
-
};
private DataLoader<String> stringCacheLoader = new DataLoader<String>() {
private DataLoader<InputStream> streamServerLoader = new DataLoader<InputStream>() {
@Override
public InputStream load(String id) throws IOException {
- InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, getReadTimeout());
- try {
- cache.put(id, is);
- } catch (IOException e) {
- throw new IllegalStateException("Error saving to WS cache", e);
+ GetRequest getRequest = new GetRequest(id);
+ try (InputStream is = client.wsConnector().call(getRequest).getContentStream()) {
+ try {
+ cache.put(id, is);
+ } catch (IOException e) {
+ throw new IllegalStateException("Error saving to WS cache", e);
+ }
}
- is.close();
return cache.getStream(id);
}
};
}
};
- private class NotAvailableException extends Exception {
+ private static class NotAvailableException extends Exception {
private static final long serialVersionUID = 1L;
public NotAvailableException(String message) {
}
}
- public WSLoader(LoadStrategy strategy, PersistentCache cache, ServerClient client, UserProperties settings) {
+ public WSLoader(LoadStrategy strategy, PersistentCache cache, WsClient client) {
this.defautLoadStrategy = strategy;
- this.userProperties = settings;
this.serverStatus = UNKNOWN;
this.cache = cache;
this.client = client;
}
- private int getReadTimeout() {
- return userProperties.properties().containsKey(SONAR_WS_TIMEOUT_PROPS) ? (Integer.parseInt(userProperties.property(SONAR_WS_TIMEOUT_PROPS)) * 1000) : DEFAULT_READ_TIMEOUT;
- }
-
@Nonnull
public WSLoaderResult<InputStream> loadStream(String id) {
return load(id, defautLoadStrategy, streamServerLoader, streamCacheLoader);
throw new IllegalStateException(FAIL_MSG, serverNotAvailable.getCause());
}
}
- throw new IllegalStateException("Server is not available", serverNotAvailable.getCause());
+ throw new IllegalStateException("Server is not available: " + client.wsConnector().baseUrl(), serverNotAvailable.getCause());
}
}
*/
package org.sonar.batch.report;
-import com.github.kevinsawicki.http.HttpRequest;
import com.google.common.annotations.VisibleForTesting;
-import com.google.gson.Gson;
-import java.io.BufferedWriter;
+import com.google.common.io.Files;
+import com.squareup.okhttp.HttpUrl;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.OutputStreamWriter;
import java.io.Writer;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.util.Date;
-import javax.annotation.CheckForNull;
+import java.util.LinkedHashMap;
+import java.util.Map;
import javax.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.picocontainer.Startable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
-import org.sonar.api.platform.Server;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.ZipUtils;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.batch.analysis.DefaultAnalysisMode;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.scan.ImmutableProjectReactor;
-import org.sonar.batch.util.BatchUtils;
+import org.sonarqube.ws.WsCe;
+import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.ce.SubmitWsRequest;
-import static java.lang.String.format;
+import static org.apache.commons.lang.StringUtils.defaultIfBlank;
@BatchSide
public class ReportPublisher implements Startable {
- private static final Logger LOG = LoggerFactory.getLogger(ReportPublisher.class);
+ private static final Logger LOG = Loggers.get(ReportPublisher.class);
+
public static final String KEEP_REPORT_PROP_KEY = "sonar.batch.keepReport";
public static final String VERBOSE_KEY = "sonar.verbose";
- public static final String DUMP_REPORT_PROP_KEY = "sonar.batch.dumpReportDir";
- public static final String JSON_DETAILS_FILE = "analysis-details.json";
+ public static final String METADATA_DUMP_FILENAME = "analysis-details.json";
- private final ServerClient serverClient;
- private final Server server;
private final Settings settings;
+ private final WsClient wsClient;
+ private final AnalysisContextReportPublisher contextPublisher;
private final ImmutableProjectReactor projectReactor;
private final DefaultAnalysisMode analysisMode;
private final TempFolder temp;
- private final AnalysisContextReportPublisher contextPublisher;
-
- private ReportPublisherStep[] publishers;
+ private final ReportPublisherStep[] publishers;
private File reportDir;
private BatchReportWriter writer;
- public ReportPublisher(Settings settings, ServerClient serverClient, Server server, AnalysisContextReportPublisher contextPublisher,
+ public ReportPublisher(Settings settings, WsClient wsClient, AnalysisContextReportPublisher contextPublisher,
ImmutableProjectReactor projectReactor, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers) {
- this.serverClient = serverClient;
- this.server = server;
+ this.settings = settings;
+ this.wsClient = wsClient;
this.contextPublisher = contextPublisher;
this.projectReactor = projectReactor;
- this.settings = settings;
this.analysisMode = analysisMode;
this.temp = temp;
this.publishers = publishers;
if (!settings.getBoolean(KEEP_REPORT_PROP_KEY) && !settings.getBoolean(VERBOSE_KEY)) {
FileUtils.deleteQuietly(reportDir);
} else {
- LOG.info("Batch report generated in " + reportDir);
+ LOG.info("Analysis report generated in " + reportDir);
}
}
// If this is a issues mode analysis then we should not upload reports
String taskId = null;
if (!analysisMode.isIssues()) {
- File report = prepareReport();
+ File report = generateReportFile();
if (!analysisMode.isMediumTest()) {
- taskId = sendOrDumpReport(report);
+ taskId = upload(report);
}
}
- logSuccess(LoggerFactory.getLogger(getClass()), taskId);
+ logSuccess(taskId);
}
- private File prepareReport() {
+ private File generateReportFile() {
try {
long startTime = System.currentTimeMillis();
for (ReportPublisherStep publisher : publishers) {
publisher.publish(writer);
}
long stopTime = System.currentTimeMillis();
- LOG.info("Analysis reports generated in " + (stopTime - startTime) + "ms, dir size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOfDirectory(reportDir)));
+ LOG.info("Analysis report generated in " + (stopTime - startTime) + "ms, dir size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOfDirectory(reportDir)));
startTime = System.currentTimeMillis();
File reportZip = temp.newFile("batch-report", ".zip");
LOG.info("Analysis reports compressed in " + (stopTime - startTime) + "ms, zip size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(reportZip)));
return reportZip;
} catch (IOException e) {
- throw new IllegalStateException("Unable to prepare batch report", e);
+ throw new IllegalStateException("Unable to prepare analysis report", e);
}
}
- @CheckForNull
+ /**
+ * Uploads the report file to server and returns the generated task id
+ */
@VisibleForTesting
- String sendOrDumpReport(File report) {
- ProjectDefinition projectDefinition = projectReactor.getRoot();
- String effectiveKey = projectDefinition.getKeyWithBranch();
- String relativeUrl = String.format("/api/ce/submit?projectKey=%s&projectName=%s&projectBranch=%s",
- projectDefinition.getKey(), BatchUtils.encodeForUrl(projectDefinition.getName()), BatchUtils.encodeForUrl(projectDefinition.getBranch()));
-
- String dumpDirLocation = settings.getString(DUMP_REPORT_PROP_KEY);
- if (dumpDirLocation == null) {
- return uploadMultiPartReport(report, relativeUrl);
- } else {
- dumpReport(dumpDirLocation, effectiveKey, relativeUrl, report);
- return null;
- }
- }
-
- private String uploadMultiPartReport(File report, String relativeUrl) {
- LOG.debug("Publish results");
+ String upload(File report) {
+ LOG.debug("Upload report");
long startTime = System.currentTimeMillis();
- URL url;
- try {
- url = new URL(serverClient.getURL() + relativeUrl);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("Invalid URL", e);
- }
- HttpRequest request = HttpRequest.post(url);
- request.trustAllCerts();
- request.trustAllHosts();
- request.header("User-Agent", format("SonarQube %s", server.getVersion()));
- request.basic(serverClient.getLogin(), serverClient.getPassword());
- request.part("report", null, "application/octet-stream", report);
- if (!request.ok()) {
- throw serverClient.handleHttpException(url.toString(), request.code(), request.body(), null);
- }
+ 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 reports sent to server in " + (stopTime - startTime) + "ms");
- String responseStr = request.body();
- SubmitResponse response = new Gson().fromJson(responseStr, SubmitResponse.class);
- return response.getTaskId();
- }
-
- private static class SubmitResponse {
- private String taskId;
-
- public String getTaskId() {
- return taskId;
- }
-
- public void setTaskId(String taskId) {
- this.taskId = taskId;
- }
- }
-
- private static void dumpReport(String dumpDirLocation, String projectKey, String relativeUrl, File report) {
- LOG.debug("Dump report to file");
- try {
- dumpReportImpl(dumpDirLocation, projectKey, relativeUrl, report);
- } catch (IOException | URISyntaxException e) {
- LOG.error("Failed to dump report to directory " + dumpDirLocation, e);
- }
- }
-
- private static void dumpReportImpl(String dumpDirLocation, String projectKey, String relativeUrl, File report) throws IOException, URISyntaxException {
- File dumpDir = new File(dumpDirLocation);
- if (!dumpDir.exists() || !dumpDir.isDirectory()) {
- LOG.warn("Report dump directory '{}' does not exist or is not a directory", dumpDirLocation);
- return;
- }
- long dateTime = new Date().getTime();
- File dumpedZip = new File(dumpDir, format("batch-report_%s_%s.zip", projectKey, dateTime));
- FileUtils.copyFile(report, new FileOutputStream(dumpedZip));
- File dumpedMetadata = new File(dumpDir, format("batch-report_%s_%s.txt", projectKey, dateTime));
- FileUtils.write(dumpedMetadata, relativeUrl);
- LOG.info("Batch report dumped to {}", dumpedZip.getAbsolutePath());
+ LOG.info("Analysis report uploaded in " + (stopTime - startTime) + "ms");
+ return submitResponse.getTaskId();
}
@VisibleForTesting
- void logSuccess(Logger logger, @Nullable String taskId) {
- if (analysisMode.isIssues() || analysisMode.isMediumTest()) {
- logger.info("ANALYSIS SUCCESSFUL");
-
+ void logSuccess(@Nullable String taskId) {
+ if (taskId == null) {
+ LOG.info("ANALYSIS SUCCESSFUL");
} else {
- String baseUrl = settings.getString(CoreProperties.SERVER_BASE_URL);
- if (baseUrl.equals(settings.getDefaultValue(CoreProperties.SERVER_BASE_URL))) {
- // If server base URL was not configured in Sonar server then is is better to take URL configured on batch side
- baseUrl = serverClient.getURL();
- }
- if (!baseUrl.endsWith("/")) {
- baseUrl += "/";
- }
+ Map<String, String> metadata = new LinkedHashMap<>();
String effectiveKey = projectReactor.getRoot().getKeyWithBranch();
- String url = baseUrl + "dashboard/index/" + effectiveKey;
- logger.info("ANALYSIS SUCCESSFUL, you can browse {}", url);
- logger.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.");
- String taskUrl = null;
- if (taskId != null) {
- taskUrl = baseUrl + "api/ce/task?id=" + taskId;
- logger.info("More about the report processing at {}", taskUrl);
- }
-
- writeJson(url, taskUrl);
+ metadata.put("projectKey", effectiveKey);
+
+ URL dashboardUrl = HttpUrl.parse(publicUrl()).newBuilder()
+ .addPathSegment("dashboard").addPathSegment("index").addPathSegment(effectiveKey)
+ .build()
+ .url();
+ metadata.put("dashboardUrl", dashboardUrl.toExternalForm());
+
+ URL taskUrl = HttpUrl.parse(publicUrl()).newBuilder()
+ .addPathSegment("api").addPathSegment("ce").addPathSegment("task")
+ .addQueryParameter("id", taskId)
+ .build()
+ .url();
+ metadata.put("ceTaskId", taskId);
+ metadata.put("ceTaskUrl", taskUrl.toExternalForm());
+
+ LOG.info("ANALYSIS SUCCESSFUL, you can browse {}", dashboardUrl);
+ LOG.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report");
+ LOG.info("More about the report processing at {}", taskUrl);
+
+ dumpMetadata(metadata);
}
}
- private void writeJson(String dashboardUrl, @Nullable String taskUrl) {
- File exportFile = new File(projectReactor.getRoot().getWorkDir(), JSON_DETAILS_FILE);
- try (Writer output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(exportFile), StandardCharsets.UTF_8))) {
+ private void dumpMetadata(Map<String, String> metadata) {
+ File file = new File(projectReactor.getRoot().getWorkDir(), METADATA_DUMP_FILENAME);
+ try (Writer output = Files.newWriter(file, StandardCharsets.UTF_8)) {
JsonWriter json = JsonWriter.of(output);
json.beginObject();
- json.prop("dashboardUrl", dashboardUrl);
- if (taskUrl != null) {
- json.prop("ceTaskUrl", taskUrl);
+ for (Map.Entry<String, String> entry : metadata.entrySet()) {
+ json.prop(entry.getKey(), entry.getValue());
}
json.endObject();
- LOG.debug("Analysis URLs written to {}", exportFile);
+ LOG.debug("Report metadata written to {}", file);
} catch (IOException e) {
- throw new IllegalStateException("Unable to write analysis URLs in file " + exportFile.getAbsolutePath(), e);
+ 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 com.google.common.base.Throwables;
-import org.sonar.api.utils.HttpDownloader.HttpException;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import java.io.IOException;
import java.io.InputStream;
+import java.net.HttpURLConnection;
import java.util.Date;
import java.util.Map;
import org.sonarqube.ws.WsBatch.WsProjectResponse;
import org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath;
import org.sonarqube.ws.WsBatch.WsProjectResponse.Settings;
+import org.sonarqube.ws.client.HttpException;
public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoader {
private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectRepositoriesLoader.class);
for (Throwable t : Throwables.getCausalChain(e)) {
if (t instanceof HttpException) {
HttpException http = (HttpException) t;
- return http.getResponseCode() != 404;
+ return http.code() != HttpURLConnection.HTTP_NOT_FOUND;
}
}
import java.io.IOException;
import java.io.InputStream;
-import java.util.Collection;
import java.util.List;
+import static com.google.common.base.Preconditions.checkState;
+
public class DefaultQualityProfileLoader implements QualityProfileLoader {
private static final String WS_URL = "/api/qualityprofiles/search.protobuf";
return loadResource(url, fromCache);
}
- private static void validate(Collection<QualityProfile> profiles) {
- if (profiles == null || profiles.isEmpty()) {
- throw new IllegalStateException("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");
- }
- }
-
private List<QualityProfile> loadResource(String url, @Nullable MutableBoolean fromCache) {
WSLoaderResult<InputStream> result = wsLoader.loadStream(url);
if (fromCache != null) {
}
List<QualityProfile> profilesList = profiles.getProfilesList();
- validate(profilesList);
+ checkState(profilesList != null && !profilesList.isEmpty(),
+ "No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");
return profilesList;
}
*/
package org.sonar.batch.analysis;
-import java.util.HashMap;
-import java.util.Map;
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.ServerClient;
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;
private PersistentCache cache;
@Mock
- private ServerClient client;
+ private WsClient client;
@Mock
private AnalysisMode mode;
private AnalysisWSLoaderProvider loaderProvider;
- private Map<String, String> propMap;
- private AnalysisProperties props;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
loaderProvider = new AnalysisWSLoaderProvider();
- propMap = new HashMap<>();
}
@Test
public void testDefault() {
- props = new AnalysisProperties(propMap, null);
-
- WSLoader loader = loaderProvider.provide(props, mode, cache, client);
+ WSLoader loader = loaderProvider.provide(mode, cache, client);
assertThat(loader.getDefaultStrategy()).isEqualTo(LoadStrategy.SERVER_ONLY);
}
}
*/
package org.sonar.batch.bootstrap;
-import org.sonar.batch.cache.WSLoaderResult;
-
-import org.sonar.batch.cache.WSLoader;
+import java.io.File;
+import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
+import org.sonar.batch.cache.WSLoader;
+import org.sonar.batch.cache.WSLoaderResult;
import org.sonar.core.platform.RemotePlugin;
import org.sonar.home.cache.FileCache;
-
-import java.io.File;
-import java.util.List;
+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);
- ServerClient serverClient = mock(ServerClient.class);
+ WsClient wsClient = mock(WsClient.class);
BatchPluginPredicate pluginPredicate = mock(BatchPluginPredicate.class);
@Test
public void listRemotePlugins() {
WSLoader wsLoader = mock(WSLoader.class);
- when(wsLoader.loadString("/deploy/plugins/index.txt")).thenReturn(new WSLoaderResult<String>("checkstyle\nsqale", true));
- BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, serverClient, fileCache, pluginPredicate);
+ when(wsLoader.loadString("/deploy/plugins/index.txt")).thenReturn(new WSLoaderResult<>("checkstyle\nsqale", true));
+ BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, wsClient, fileCache, pluginPredicate);
List<RemotePlugin> remotePlugins = installer.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, serverClient, fileCache, pluginPredicate);
+ BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, wsClient, fileCache, pluginPredicate);
RemotePlugin remote = new RemotePlugin("checkstyle").setFile("checkstyle-plugin.jar", "fakemd5_1");
File file = installer.download(remote);
WSLoader wsLoader = mock(WSLoader.class);
doThrow(new IllegalStateException()).when(wsLoader).loadString("/deploy/plugins/index.txt");
- new BatchPluginInstaller(wsLoader, serverClient, fileCache, pluginPredicate).installRemotes();
+ new BatchPluginInstaller(wsLoader, wsClient, fileCache, pluginPredicate).installRemotes();
}
}
+++ /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.sonar.batch.util.BatchUtils;
-
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-
-import org.junit.After;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ServerClientTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private MockHttpServer server = null;
- private GlobalProperties bootstrapProps = mock(GlobalProperties.class);
-
- @After
- public void stopServer() {
- if (server != null) {
- server.stop();
- }
- }
-
- @Test
- public void should_remove_url_ending_slash() {
- GlobalProperties settings = mock(GlobalProperties.class);
- when(settings.property("sonar.host.url")).thenReturn("http://localhost:8080/sonar/");
- ServerClient client = new ServerClient(settings, new EnvironmentInformation("Junit", "4"));
-
- assertThat(client.getURL()).isEqualTo("http://localhost:8080/sonar");
- }
-
- @Test
- public void should_request_url() throws Exception {
- startServer(null, "this is the content");
- assertThat(newServerClient().downloadString("/foo")).isEqualTo("this is the content");
- }
-
- @Test
- public void should_escape_html_from_url() throws Exception {
- startServer(null, "this is the content");
- assertThat(newServerClient().downloadString("/<foo>")).isEqualTo("this is the content");
- }
-
- @Test
- public void should_download_file() throws Exception {
- startServer(null, "this is the content");
- File file = temp.newFile();
- newServerClient().download("/foo", file);
- assertThat(new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8)).isEqualTo("this is the content");
- }
-
- @Test
- public void should_fail_if_unauthorized_with_no_login_password() throws Exception {
- startServer(401, null);
- thrown.expectMessage("Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
- newServerClient().downloadString("/foo");
- }
-
- @Test
- public void should_fail_if_unauthorized_with_login_password_provided() throws Exception {
- startServer(401, null);
-
- when(bootstrapProps.property(eq("sonar.login"))).thenReturn("login");
- when(bootstrapProps.property(eq("sonar.password"))).thenReturn("password");
-
- thrown.expectMessage("Not authorized. Please check the properties sonar.login and sonar.password");
- newServerClient().downloadString("/foo");
- }
-
- @Test
- public void should_display_json_error_when_403() throws Exception {
- startServer(403, "{\"errors\":[{\"msg\":\"Insufficient privileges\"}]}");
- thrown.expectMessage("Insufficient privileges");
- newServerClient().downloadString("/foo");
- }
-
- @Test
- public void should_fail_if_error() throws Exception {
- startServer(500, null);
- thrown.expectMessage("Fail to execute request [code=500, url=http://localhost:" + server.getPort() + "/foo]");
- newServerClient().downloadString("/foo");
- }
-
- @Test
- public void string_encode() {
- assertThat(BatchUtils.encodeForUrl("my value")).isEqualTo("my+value");
- }
-
- private ServerClient newServerClient() {
- when(bootstrapProps.property("sonar.host.url")).thenReturn("http://localhost:" + server.getPort());
- return new ServerClient(bootstrapProps, new EnvironmentInformation("Junit", "4"));
- }
-
- private void startServer(Integer responseStatus, String responseData) throws Exception {
- server = new MockHttpServer();
- server.start();
-
- if (responseStatus != null) {
- server.setMockResponseStatus(responseStatus);
- }
- if (responseData != null) {
- server.setMockResponseData(responseData);
- }
- }
-}
--- /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);
+ }
+}
*/
package org.sonar.batch.cache;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.io.Files;
-import org.junit.rules.ExpectedException;
-
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
-
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.junit.Rule;
-import org.junit.Before;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.home.cache.PersistentCache;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
public class DefaultProjectCacheStatusTest {
@Rule
public TemporaryFolder tmp = new TemporaryFolder();
public ExpectedException exception = ExpectedException.none();
ProjectCacheStatus cacheStatus;
- PersistentCache cache;
- ServerClient client;
+ PersistentCache cache = mock(PersistentCache.class);
@Before
public void setUp() {
- client = mock(ServerClient.class);
- cache = mock(PersistentCache.class);
when(cache.getDirectory()).thenReturn(tmp.getRoot().toPath());
cacheStatus = new DefaultProjectCacheStatus(cache);
}
*/
package org.sonar.batch.cache;
-import org.sonar.batch.protocol.input.ProjectRepositories;
-
+import java.util.HashMap;
+import org.junit.Test;
import org.sonar.batch.bootstrap.GlobalProperties;
-import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.home.cache.PersistentCache;
-
-import java.util.HashMap;
+import org.sonarqube.ws.client.WsClient;
import static org.mockito.Mockito.mock;
-import org.sonar.core.platform.ComponentContainer;
-import org.junit.Test;
public class ProjectSyncContainerTest {
private ComponentContainer createParentContainer() {
PersistentCache cache = mock(PersistentCache.class);
- ServerClient server = mock(ServerClient.class);
+ WsClient server = mock(WsClient.class);
GlobalProperties globalProps = new GlobalProperties(new HashMap<String, String>());
ComponentContainer parent = new ComponentContainer();
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.sonar.batch.bootstrap.GlobalProperties;
-import org.sonar.batch.bootstrap.ServerClient;
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 StrategyWSLoaderProviderTest {
@Mock
private PersistentCache cache;
@Mock
- private ServerClient client;
-
- private GlobalProperties globalProps;
+ private WsClient client;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- globalProps = mock(GlobalProperties.class);
}
@Test
public void testStrategy() {
StrategyWSLoaderProvider provider = new StrategyWSLoaderProvider(LoadStrategy.CACHE_FIRST);
- WSLoader wsLoader = provider.provide(cache, client, globalProps);
+ WSLoader wsLoader = provider.provide(cache, client);
assertThat(wsLoader.getDefaultStrategy()).isEqualTo(LoadStrategy.CACHE_FIRST);
}
@Test
public void testSingleton() {
StrategyWSLoaderProvider provider = new StrategyWSLoaderProvider(LoadStrategy.CACHE_FIRST);
- WSLoader wsLoader = provider.provide(cache, client, globalProps);
+ WSLoader wsLoader = provider.provide(cache, client);
- assertThat(provider.provide(null, null, null)).isEqualTo(wsLoader);
+ assertThat(provider.provide(null, null)).isEqualTo(wsLoader);
}
}
*/
package org.sonar.batch.cache;
-import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URI;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.InOrder;
-import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.utils.HttpDownloader;
-import org.sonar.batch.bootstrap.ServerClient;
-import org.sonar.batch.bootstrap.UserProperties;
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;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
private final static String cacheValue = "cache";
private final static String serverValue = "server";
- @Mock
- private ServerClient client;
- @Mock
- private PersistentCache cache;
@Rule
public ExpectedException exception = ExpectedException.none();
- private UserProperties props;
- @Before
- public void setUp() throws IOException {
- MockitoAnnotations.initMocks(this);
- when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenReturn(IOUtils.toInputStream(serverValue));
- when(cache.getString(ID)).thenReturn(cacheValue);
- when(client.getURI(anyString())).thenAnswer(new Answer<URI>() {
- @Override
- public URI answer(InvocationOnMock invocation) throws Throwable {
- return new URI((String) invocation.getArguments()[0]);
- }
- });
- props = mock(UserProperties.class);
- }
+ WsClient ws = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
+ PersistentCache cache = mock(PersistentCache.class);
@Test
public void dont_retry_server_offline() throws IOException {
turnServerOffline();
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ when(cache.getString(ID)).thenReturn(cacheValue);
+ WSLoader underTest = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
- assertResult(loader.loadString(ID), cacheValue, true);
- assertResult(loader.loadString(ID), cacheValue, true);
+ assertResult(underTest.loadString(ID), cacheValue, true);
+ assertResult(underTest.loadString(ID), cacheValue, true);
assertUsedServer(1);
assertUsedCache(2);
@Test
public void get_stream_from_cache() throws IOException {
- InputStream is = mock(InputStream.class);
+ InputStream is = IOUtils.toInputStream("is");
when(cache.getStream(ID)).thenReturn(is);
- WSLoader loader = new WSLoader(LoadStrategy.CACHE_FIRST, cache, client, props);
- WSLoaderResult<InputStream> result = loader.loadStream(ID);
- assertThat(result.get()).isEqualTo(is);
- verify(cache).getStream(ID);
- verifyNoMoreInteractions(cache, client);
- }
-
- @Test
- public void put_stream_in_cache() throws IOException {
- InputStream is1 = mock(InputStream.class);
- InputStream is2 = mock(InputStream.class);
-
- when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenReturn(is1);
- when(cache.getStream(ID)).thenReturn(is2);
-
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.CACHE_FIRST, cache, ws);
WSLoaderResult<InputStream> result = loader.loadStream(ID);
- assertThat(result.get()).isEqualTo(is2);
- verify(client).load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt());
- verify(cache).put(ID, is1);
+ assertThat(result.get()).isEqualTo(is);
verify(cache).getStream(ID);
-
- verifyNoMoreInteractions(cache, client);
+ verifyNoMoreInteractions(cache, ws);
}
@Test
- public void default_timeout() throws IOException {
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
- loader.loadStream(ID);
-
- verify(client).load(anyString(), anyString(), anyBoolean(), anyInt(), eq(60_000));
-
- verifyNoMoreInteractions(client);
- }
-
- @Test
- public void change_timeout() throws IOException {
- when(props.properties()).thenReturn(ImmutableMap.of(WSLoader.SONAR_WS_TIMEOUT_PROPS, "20"));
- when(props.property(WSLoader.SONAR_WS_TIMEOUT_PROPS)).thenReturn("20");
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
- loader.loadStream(ID);
-
- verify(client).load(anyString(), anyString(), anyBoolean(), anyInt(), eq(20_000));
-
- verifyNoMoreInteractions(client);
+ 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(cache.getStream(ID)).thenReturn(input);
+
+ // SERVER_FIRST -> load from server then put to cache
+ WSLoader underTest = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
+ 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.verify(cache).put(eq(ID), any(InputStream.class));
+ inOrder.verify(cache).getStream(ID);
+ verifyNoMoreInteractions(cache, wsConnector);
}
@Test
public void test_cache_strategy_fallback() throws IOException {
turnCacheEmpty();
- WSLoader loader = new WSLoader(LoadStrategy.CACHE_FIRST, cache, client, props);
+ when(ws.wsConnector().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 = Mockito.inOrder(client, cache);
+ InOrder inOrder = inOrder(ws.wsConnector(), cache);
inOrder.verify(cache).getString(ID);
- inOrder.verify(client).load(eq(ID), anyString(), anyBoolean(), anyInt(), anyInt());
+ inOrder.verify(ws.wsConnector()).call(any(WsRequest.class));
}
@Test
public void test_server_strategy_fallback() throws IOException {
turnServerOffline();
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ when(cache.getString(ID)).thenReturn(cacheValue);
+ WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
assertResult(loader.loadString(ID), cacheValue, true);
- InOrder inOrder = Mockito.inOrder(client, cache);
- inOrder.verify(client).load(eq(ID), anyString(), anyBoolean(), anyInt(), anyInt());
+ InOrder inOrder = inOrder(ws.wsConnector(), cache);
+ inOrder.verify(ws.wsConnector()).call(any(WsRequest.class));
inOrder.verify(cache).getString(ID);
}
@Test
public void test_put_cache() throws IOException {
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ when(ws.wsConnector().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());
}
turnServerOffline();
when(cache.getString(ID)).thenThrow(new NullPointerException());
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
try {
loader.loadString(ID);
public void test_throw_cache_exception() throws IOException {
when(cache.getString(ID)).thenThrow(new IllegalStateException());
- WSLoader loader = new WSLoader(LoadStrategy.CACHE_FIRST, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.CACHE_FIRST, cache, ws);
try {
loader.loadString(ID);
@Test
public void test_throw_http_exceptions() {
- HttpDownloader.HttpException httpException = mock(HttpDownloader.HttpException.class);
+ HttpException httpException = new HttpException("url", 500, "Internal Error");
IllegalStateException wrapperException = new IllegalStateException(httpException);
- when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(wrapperException);
+ when(ws.wsConnector().call(any(WsRequest.class))).thenThrow(wrapperException);
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
try {
loader.loadString(ID);
turnServerOffline();
exception.expect(IllegalStateException.class);
- exception.expectMessage(Matchers.is("Server is not available"));
+ exception.expectMessage(Matchers.containsString("Server is not available"));
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_ONLY, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.SERVER_ONLY, cache, ws);
loader.loadString(ID);
}
exception.expect(IllegalStateException.class);
exception.expectMessage(Matchers.is("Server is not accessible and data is not cached"));
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
loader.loadString(ID);
}
exception.expect(IllegalStateException.class);
exception.expectMessage(Matchers.is("Data is not cached"));
- WSLoader loader = new WSLoader(LoadStrategy.CACHE_ONLY, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.CACHE_ONLY, cache, ws);
loader.loadString(ID);
}
@Test
public void test_server_strategy() throws IOException {
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ when(ws.wsConnector().call(any(WsRequest.class))).thenReturn(new MockWsResponse().setContent(serverValue));
+ WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, ws);
assertResult(loader.loadString(ID), serverValue, false);
// should not fetch from cache
@Test(expected = IllegalStateException.class)
public void test_server_only() throws IOException {
turnServerOffline();
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_ONLY, cache, client, props);
+ WSLoader loader = new WSLoader(LoadStrategy.SERVER_ONLY, cache, ws);
loader.loadString(ID);
}
@Test
public void test_string() {
- WSLoader loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, props);
+ when(ws.wsConnector().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(client, times(times)).load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt());
- }
-
- private void assertResult(WSLoaderResult<InputStream> result, byte[] expected, boolean fromCache) throws IOException {
- byte[] content = IOUtils.toByteArray(result.get());
- assertThat(result).isNotNull();
- assertThat(content).isEqualTo(expected);
- assertThat(result.isFromCache()).isEqualTo(fromCache);
+ verify(ws.wsConnector(), times(times)).call(any(WsRequest.class));
}
private void assertResult(WSLoaderResult<String> result, String expected, boolean fromCache) {
}
private void turnServerOffline() {
- when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
+ when(ws.wsConnector().call(any(WsRequest.class))).thenThrow(new IllegalStateException());
}
private void turnCacheEmpty() throws IOException {
+++ /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.cache;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.batch.bootstrap.GlobalProperties;
-import org.sonar.batch.bootstrap.MockHttpServer;
-import org.sonar.batch.bootstrap.ServerClient;
-import org.sonar.batch.bootstrap.Slf4jLogger;
-import org.sonar.batch.bootstrap.UserProperties;
-import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import org.sonar.batch.cache.WSLoader.LoadStrategy;
-import org.sonar.home.cache.DirectoryLock;
-import org.sonar.home.cache.PersistentCache;
-import org.sonar.home.cache.TTLCacheInvalidation;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class WSLoaderWithServerTest {
- private static final String RESPONSE_STRING = "this is the content";
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- private MockHttpServer server;
- private PersistentCache cache;
- private ServerClient client;
- private WSLoader loader;
- private UserProperties userProps;
-
- @Before
- public void setUp() throws Exception {
- server = new MockHttpServer();
- server.start();
-
- GlobalProperties bootstrapProps = mock(GlobalProperties.class);
- when(bootstrapProps.property("sonar.host.url")).thenReturn("http://localhost:" + server.getPort());
-
- client = new ServerClient(bootstrapProps, new EnvironmentInformation("Junit", "4"));
- cache = new PersistentCache(temp.getRoot().toPath(), new TTLCacheInvalidation(100_000L), new Slf4jLogger(), mock(DirectoryLock.class));
- userProps = mock(UserProperties.class);
- }
-
- @After
- public void tearDown() {
- if (server != null) {
- server.stop();
- }
- }
-
- @Test
- public void testCacheOnly() {
- loader = new WSLoader(LoadStrategy.SERVER_ONLY, cache, client, userProps);
- makeRequests();
-
- loader = new WSLoader(LoadStrategy.CACHE_ONLY, cache, client, userProps);
- makeRequests();
- assertThat(server.getNumberRequests()).isEqualTo(3);
- }
-
- @Test
- public void testCacheFirst() {
- loader = new WSLoader(LoadStrategy.CACHE_FIRST, cache, client, userProps);
- makeRequests();
- assertThat(server.getNumberRequests()).isEqualTo(1);
- }
-
- @Test
- public void testServerFirst() {
- loader = new WSLoader(LoadStrategy.SERVER_FIRST, cache, client, userProps);
- makeRequests();
- assertThat(server.getNumberRequests()).isEqualTo(3);
- }
-
- @Test
- public void testCacheStrategyDisabled() {
- loader = new WSLoader(LoadStrategy.SERVER_ONLY, cache, client, userProps);
- makeRequests();
- assertThat(server.getNumberRequests()).isEqualTo(3);
- }
-
- private void makeRequests() {
- server.setMockResponseData(RESPONSE_STRING);
- assertThat(loader.loadString("/foo").get()).isEqualTo(RESPONSE_STRING);
- assertThat(loader.loadString("/foo").get()).isEqualTo(RESPONSE_STRING);
- assertThat(loader.loadString("/foo").get()).isEqualTo(RESPONSE_STRING);
- }
-
-}
*/
package org.sonar.batch.report;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.slf4j.Logger;
+import org.mockito.Mockito;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
-import org.sonar.api.platform.Server;
import org.sonar.api.utils.TempFolder;
+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.ServerClient;
import org.sonar.batch.scan.ImmutableProjectReactor;
+import org.sonar.test.JsonAssert;
+import org.sonarqube.ws.client.WsClient;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
+import static org.apache.commons.io.FileUtils.readFileToString;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
public class ReportPublisherTest {
- private DefaultAnalysisMode mode;
-
- private ImmutableProjectReactor reactor;
-
- private Settings settings;
-
- private ProjectDefinition root;
+ @Rule
+ public LogTester logTester = new LogTester();
@Rule
public TemporaryFolder temp = new TemporaryFolder();
+ DefaultAnalysisMode mode = mock(DefaultAnalysisMode.class);
+ Settings settings = new Settings();
+ WsClient wsClient = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
+ ImmutableProjectReactor reactor = mock(ImmutableProjectReactor.class);
+ ProjectDefinition root;
+ AnalysisContextReportPublisher contextPublisher = mock(AnalysisContextReportPublisher.class);
+
@Before
public void setUp() {
- settings = new Settings();
- mode = mock(DefaultAnalysisMode.class);
- reactor = mock(ImmutableProjectReactor.class);
root = ProjectDefinition.create().setKey("struts").setWorkDir(temp.getRoot());
when(reactor.getRoot()).thenReturn(root);
+ when(wsClient.wsConnector().baseUrl()).thenReturn("https://localhost");
}
@Test
- public void should_log_successful_analysis() {
- settings.setProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/");
- ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), mock(AnalysisContextReportPublisher.class), reactor, mode,
- mock(TempFolder.class), new ReportPublisherStep[0]);
-
- Logger logger = mock(Logger.class);
- job.logSuccess(logger, null);
-
- verify(logger).info("ANALYSIS SUCCESSFUL, you can browse {}", "http://myserver/dashboard/index/struts");
- verify(logger).info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.");
- verifyNoMoreInteractions(logger);
+ public void log_and_dump_information_about_report_uploading() throws IOException {
+ 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://localhost/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");
+
+ File detailsFile = new File(temp.getRoot(), "analysis-details.json");
+ JsonAssert.assertJson(readFileToString(detailsFile)).isSimilarTo("{" +
+ "\"projectKey\": \"struts\"," +
+ "\"dashboardUrl\": \"https://localhost/dashboard/index/struts\"," +
+ "\"ceTaskId\": \"TASK-123\"," +
+ "\"ceTaskUrl\": \"https://localhost/api/ce/task?id=TASK-123\"" +
+ "}"
+ );
}
@Test
- public void should_log_successful_analysis_with_ce_task() {
- settings.setProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/");
- ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), mock(AnalysisContextReportPublisher.class), reactor, mode,
- mock(TempFolder.class), new ReportPublisherStep[0]);
-
- Logger logger = mock(Logger.class);
- job.logSuccess(logger, "abc123");
-
- verify(logger).info("ANALYSIS SUCCESSFUL, you can browse {}", "http://myserver/dashboard/index/struts");
- verify(logger).info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.");
- verify(logger).info("More about the report processing at {}", "http://myserver/api/ce/task?id=abc123");
- verifyNoMoreInteractions(logger);
+ 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 should_write_json_file() throws IOException {
- settings.setProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/");
-
- ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), mock(AnalysisContextReportPublisher.class), reactor, mode,
- mock(TempFolder.class), new ReportPublisherStep[0]);
- job.logSuccess(mock(Logger.class), "abc123");
-
- File jsonFile = new File(temp.getRoot(), "analysis-details.json");
- assertThat(jsonFile).exists();
+ 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]);
- String jsonFileContent = new String(Files.readAllBytes(jsonFile.toPath()), StandardCharsets.UTF_8);
- String expectedContent = "\"dashboardUrl\":\"http://myserver/dashboard/index/struts\",\"ceTaskUrl\":\"http://myserver/api/ce/task?id=abc123\"";
- assertThat(jsonFileContent).contains(expectedContent);
+ underTest.logSuccess(/* report not uploaded, no server task */null);
- }
-
- @Test
- public void should_log_successful_issues_analysis() {
- when(mode.isIssues()).thenReturn(true);
- ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), mock(AnalysisContextReportPublisher.class), reactor, mode,
- mock(TempFolder.class), new ReportPublisherStep[0]);
+ assertThat(logTester.logs(LoggerLevel.INFO))
+ .contains("ANALYSIS SUCCESSFUL")
+ .doesNotContain("dashboard/index");
- Logger logger = mock(Logger.class);
- job.logSuccess(logger, null);
-
- verify(logger).info("ANALYSIS SUCCESSFUL");
- verifyNoMoreInteractions(logger);
+ File detailsFile = new File(temp.getRoot(), "analysis-details.json");
+ assertThat(detailsFile).doesNotExist();
}
@Test
- public void should_not_delete_report() throws IOException {
- settings.setProperty("sonar.verbose", true);
+ public void should_not_delete_report_if_property_is_set() throws IOException {
+ settings.setProperty("sonar.batch.keepReport", true);
Path reportDir = temp.getRoot().toPath().resolve("batch-report");
Files.createDirectory(reportDir);
- ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), mock(AnalysisContextReportPublisher.class), reactor, mode,
- mock(TempFolder.class), new ReportPublisherStep[0]);
+ ReportPublisher underTest = new ReportPublisher(settings, wsClient, contextPublisher, reactor, mode, mock(TempFolder.class), new ReportPublisherStep[0]);
- job.start();
- job.stop();
+ underTest.start();
+ underTest.stop();
assertThat(reportDir).isDirectory();
}
@Test
- public void should_delete_report() throws IOException {
+ public void should_delete_report_by_default() throws IOException {
Path reportDir = temp.getRoot().toPath().resolve("batch-report");
Files.createDirectory(reportDir);
- ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), mock(AnalysisContextReportPublisher.class), reactor, mode,
- mock(TempFolder.class), new ReportPublisherStep[0]);
+ ReportPublisher job = new ReportPublisher(settings, wsClient, contextPublisher, reactor, mode, mock(TempFolder.class), new ReportPublisherStep[0]);
job.start();
job.stop();
*/
package org.sonar.batch.repository;
-import org.sonar.api.utils.MessageException;
-
import com.google.common.io.Resources;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URI;
-
-import org.sonar.api.utils.HttpDownloader.HttpException;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.MessageException;
import org.sonar.batch.cache.WSLoader;
import org.sonar.batch.cache.WSLoaderResult;
import org.sonarqube.ws.WsBatch.WsProjectResponse;
+import org.sonarqube.ws.client.HttpException;
+
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
public void prepare() throws IOException {
wsLoader = mock(WSLoader.class);
InputStream is = mockData();
- when(wsLoader.loadStream(anyString())).thenReturn(new WSLoaderResult<InputStream>(is, true));
+ when(wsLoader.loadStream(anyString())).thenReturn(new WSLoaderResult<>(is, true));
loader = new DefaultProjectRepositoriesLoader(wsLoader);
}
InputStream is = mock(InputStream.class);
when(is.read()).thenThrow(IOException.class);
- when(wsLoader.loadStream(anyString())).thenReturn(new WSLoaderResult<InputStream>(is, false));
+ when(wsLoader.loadStream(anyString())).thenReturn(new WSLoaderResult<>(is, false));
loader.load(PROJECT_KEY, false, null);
}
@Test(expected = IllegalStateException.class)
public void failFastHttpError() {
- HttpException http = new HttpException(URI.create("uri"), 403);
+ HttpException http = new HttpException("url", 403, "Forbidden");
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.create("uri"), 403);
+ HttpException http = new HttpException("uri", 403, "Forbidden");
MessageException e = MessageException.of("http error", http);
when(wsLoader.loadStream(anyString())).thenThrow(e);
loader.load(PROJECT_KEY, false, null);
<name>SonarQube :: Web Service</name>
<description>Protocol Buffers specification of Web Services</description>
+ <properties>
+ <sonar.exclusions>target/generated-sources/**/*</sonar.exclusions>
+ <sonar.test.exclusions>target/generated-test-sources/**/*</sonar.test.exclusions>
+ </properties>
+
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>${okhttp.version}</version>
+ </dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>sonar-testing-harness</artifactId>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <version>${okhttp.version}</version>
<scope>test</scope>
</dependency>
-
- <!-- Jetty dependencies -->
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>test-jetty-servlet</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.googlecode.json-simple</groupId>
- <artifactId>json-simple</artifactId>
- </dependency>
- <dependency>
- <groupId>com.github.kevinsawicki</groupId>
- <artifactId>http-request</artifactId>
- </dependency>
</dependencies>
</project>
import java.util.Map;
/**
- * @since 3.1
+ * @since 5.3
*/
public final class MediaTypes {
public static final String XML = "application/xml";
public static final String TXT = "text/plain";
public static final String PROTOBUF = "application/x-protobuf";
+ public static final String ZIP = "application/zip";
public static final String DEFAULT = "application/octet-stream";
private static final Map<String, String> MAP = new ImmutableMap.Builder<String, String>()
--- /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;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.sonarqube.ws.MediaTypes;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.util.Objects.requireNonNull;
+
+abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest {
+
+ private final String path;
+
+ private String mediaType = MediaTypes.JSON;
+
+ // keep the same order -> do not use HashMap
+ private final Map<String, String> params = new LinkedHashMap<>();
+
+ BaseRequest(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public String getMediaType() {
+ return mediaType;
+ }
+
+ /**
+ * Expected media type of response. Default is {@link MediaTypes#JSON}.
+ */
+ public SELF setMediaType(String s) {
+ requireNonNull(s, "media type of response cannot be null");
+ this.mediaType = s;
+ return (SELF) this;
+ }
+
+ public SELF setParam(String key, @Nullable Object value) {
+ checkArgument(!isNullOrEmpty(key), "a WS parameter key cannot be null");
+ if (value != null) {
+ this.params.put(key, value.toString());
+ }
+ return (SELF) this;
+ }
+
+ @Override
+ public Map<String, String> getParams() {
+ return params;
+ }
+}
--- /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;
+
+import com.google.protobuf.Message;
+import com.google.protobuf.Parser;
+import java.io.InputStream;
+import org.sonarqube.ws.MediaTypes;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+public abstract class BaseService {
+
+ private final WsConnector wsConnector;
+ private final String controller;
+
+ public BaseService(WsConnector wsConnector, String controllerPath) {
+ checkArgument(!isNullOrEmpty(controllerPath));
+ this.wsConnector = wsConnector;
+ this.controller = controllerPath;
+ }
+
+ protected <T extends Message> T call(BaseRequest request, Parser<T> parser) {
+ request.setMediaType(MediaTypes.PROTOBUF);
+ WsResponse response = wsConnector.call(request);
+ return convert(response, parser);
+ }
+
+ protected WsResponse call(WsRequest request) {
+ return wsConnector.call(request);
+ }
+
+ public <T extends Message> T convert(WsResponse response, Parser<T> parser) {
+ try (InputStream byteStream = response.getContentStream()) {
+ // 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);
+ }
+ }
+
+ protected String path(String action) {
+ return String.format("%s/%s", controller, action);
+ }
+}
--- /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;
+
+/**
+ * @since 5.3
+ */
+public class GetRequest extends BaseRequest<GetRequest> {
+ public GetRequest(String path) {
+ super(path);
+ }
+
+ @Override
+ public Method getMethod() {
+ return Method.GET;
+ }
+}
* 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 com.squareup.okhttp.Call;
+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.Request;
+import com.squareup.okhttp.RequestBody;
+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;
import javax.annotation.Nullable;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static com.google.common.base.Strings.nullToEmpty;
+import static java.lang.String.format;
+
public class HttpConnector implements WsConnector {
- public static final int DEFAULT_CONNECT_TIMEOUT_MILLISECONDS = 30000;
- public static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60000;
+ public static final int DEFAULT_CONNECT_TIMEOUT_MILLISECONDS = 30_000;
+ public static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60_000;
/**
- * Visibility relaxed for unit tests
+ * Base URL with trailing slash, for instance "https://localhost/sonarqube/".
+ * It is required for further usage of {@link HttpUrl#resolve(String)}.
*/
- final HttpRequestFactory requestFactory;
+ private final HttpUrl baseUrl;
+ private final String userAgent;
+ private final String credentials;
+ private final String proxyCredentials;
+ private final OkHttpClient okHttpClient = new OkHttpClient();
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);
+ this.baseUrl = HttpUrl.parse(builder.url.endsWith("/") ? builder.url : format("%s/", builder.url));
+ this.userAgent = builder.userAgent;
+
+ if (isNullOrEmpty(builder.login)) {
+ // no login nor access token
+ this.credentials = null;
+ } else {
+ // password is null when login represents an access token. In this case
+ // the Basic credentials consider an empty password.
+ this.credentials = Credentials.basic(builder.login, nullToEmpty(builder.password));
+ }
+
+ if (builder.proxy != null) {
+ this.okHttpClient.setProxy(builder.proxy);
+ }
+ // proxy credentials can be used on system-wide proxies, so even if builder.proxy is null
+ if (isNullOrEmpty(builder.proxyLogin)) {
+ this.proxyCredentials = null;
+ } else {
+ this.proxyCredentials = Credentials.basic(builder.proxyLogin, nullToEmpty(builder.proxyPassword));
+ }
+
+ this.okHttpClient.setConnectTimeout(builder.connectTimeoutMs, TimeUnit.MILLISECONDS);
+ this.okHttpClient.setReadTimeout(builder.readTimeoutMs, TimeUnit.MILLISECONDS);
+ this.okHttpClient.interceptors().addAll(builder.interceptors);
}
@Override
- public String execute(WsRequest wsRequest) {
- return requestFactory.execute(wsRequest);
+ public String baseUrl() {
+ return baseUrl.url().toExternalForm();
+ }
+
+ public OkHttpClient okHttpClient() {
+ return okHttpClient;
+ }
+
+ @CheckForNull
+ public String userAgent() {
+ return userAgent;
+ }
+
+ @CheckForNull
+ public String credentials() {
+ return credentials;
}
@Override
- public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) {
- return requestFactory.execute(wsRequest, protobufParser);
+ public WsResponse call(WsRequest httpRequest) {
+ if (httpRequest instanceof GetRequest) {
+ return get((GetRequest) httpRequest);
+ }
+ if (httpRequest instanceof PostRequest) {
+ return post((PostRequest) httpRequest);
+ }
+ throw new IllegalArgumentException(format("Unsupported implementation: %s", httpRequest.getClass()));
}
- /**
- * Create a builder of {@link WsClient}s.
- */
- public static Builder newHttpConnector() {
- return new Builder();
+ private WsResponse get(GetRequest getRequest) {
+ HttpUrl.Builder urlBuilder = prepareUrlBuilder(getRequest);
+ Request.Builder okRequestBuilder = prepareOkRequestBuilder(getRequest, urlBuilder).get();
+ return doCall(okRequestBuilder.build());
}
- /**
- * 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();
+ private WsResponse post(PostRequest postRequest) {
+ HttpUrl.Builder urlBuilder = prepareUrlBuilder(postRequest);
+ Request.Builder okRequestBuilder = prepareOkRequestBuilder(postRequest, urlBuilder);
+
+ Map<String, PostRequest.Part> parts = postRequest.getParts();
+ if (parts.isEmpty()) {
+ okRequestBuilder.post(RequestBody.create(null, ""));
+ } else {
+ MultipartBuilder body = new MultipartBuilder().type(MultipartBuilder.FORM);
+ for (Map.Entry<String, PostRequest.Part> param : parts.entrySet()) {
+ PostRequest.Part part = param.getValue();
+ body.addPart(
+ Headers.of("Content-Disposition", format("form-data; name=\"%s\"", param.getKey())),
+ RequestBody.create(MediaType.parse(part.getMediaType()), part.getFile()));
+ }
+ okRequestBuilder.post(body.build());
+ }
+
+ return doCall(okRequestBuilder.build());
+ }
+
+ private HttpUrl.Builder prepareUrlBuilder(WsRequest wsRequest) {
+ String path = wsRequest.getPath();
+ HttpUrl.Builder urlBuilder = baseUrl
+ .resolve(path.startsWith("/") ? path.replaceAll("^(/)+", "") : path)
+ .newBuilder();
+ for (Map.Entry<String, String> param : wsRequest.getParams().entrySet()) {
+ urlBuilder.addQueryParameter(param.getKey(), param.getValue());
+ }
+ return urlBuilder;
+ }
+
+ private Request.Builder prepareOkRequestBuilder(WsRequest getRequest, HttpUrl.Builder urlBuilder) {
+ Request.Builder okHttpRequestBuilder = new Request.Builder()
+ .url(urlBuilder.build())
+ .addHeader("Accept", getRequest.getMediaType())
+ .addHeader("Accept-Charset", "UTF-8");
+ if (credentials != null) {
+ okHttpRequestBuilder.header("Authorization", credentials);
+ }
+ if (proxyCredentials != null) {
+ okHttpRequestBuilder.header("Proxy-Authorization", proxyCredentials);
+ }
+ if (userAgent != null) {
+ okHttpRequestBuilder.addHeader("User-Agent", userAgent);
+ }
+ return okHttpRequestBuilder;
+ }
+
+ private HttpResponse doCall(Request okRequest) {
+ 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);
+ }
}
public static class Builder {
+ private String url;
+ private String userAgent;
private String login;
private String password;
- private String url;
- private String proxyHost;
+ private Proxy proxy;
private String proxyLogin;
private String proxyPassword;
- private int proxyPort = 0;
-
private int connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MILLISECONDS;
private int readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLISECONDS;
+ private final List<Interceptor> interceptors = new ArrayList<>();
- private Builder() {
+ /**
+ * Optional User Agent
+ */
+ public Builder userAgent(@Nullable String userAgent) {
+ this.userAgent = userAgent;
+ return this;
}
/**
}
/**
- * Optional login, for example "admin"
+ * Optional login/password, for example "admin"
*/
- public Builder login(@Nullable String login) {
+ public Builder credentials(@Nullable String login, @Nullable String password) {
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
+ * Optional access token, for example {@code "ABCDE"}. Alternative to {@link #credentials(String, String)}
*/
- 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;
+ public Builder token(@Nullable String token) {
+ this.login = token;
+ this.password = null;
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}
+ * A timeout of zero is interpreted as an infinite timeout. Default value is {@link #DEFAULT_CONNECT_TIMEOUT_MILLISECONDS}
*/
public Builder connectTimeoutMilliseconds(int i) {
this.connectTimeoutMs = i;
/**
* 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}
+ * A timeout of zero is interpreted as an infinite timeout. Default value is {@link #DEFAULT_READ_TIMEOUT_MILLISECONDS}
*/
public Builder readTimeoutMilliseconds(int i) {
this.readTimeoutMs = i;
return this;
}
+ public Builder proxy(@Nullable Proxy proxy) {
+ this.proxy = proxy;
+ return this;
+ }
+
+ public Builder proxyCredentials(@Nullable String proxyLogin, @Nullable String proxyPassword) {
+ this.proxyLogin = proxyLogin;
+ this.proxyPassword = proxyPassword;
+ return this;
+ }
+
/**
- * Build a new client
+ * 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() {
- if (url == null || "".equals(url)) {
- throw new IllegalStateException("Server URL must be set");
- }
+ checkArgument(!isNullOrEmpty(url), "Server URL is not defined");
return new HttpConnector(this);
}
package org.sonarqube.ws.client;
/**
- * @since 3.6
+ * @since 5.3
*/
public class HttpException extends RuntimeException {
private final String url;
- private final int status;
+ private final int code;
- public HttpException(String url, int status, String message) {
- super(String.format("Error %d on %s : %s", status, url, message));
+ public HttpException(String url, int code, String message) {
+ super(String.format("Error %d on %s : %s", code, url, message));
this.url = url;
- this.status = status;
+ this.code = code;
}
public String url() {
return url;
}
- public int status() {
- return status;
+ /**
+ * @see java.net.HttpURLConnection constants
+ */
+ public int code() {
+ return code;
}
}
+++ /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;
-
-import com.github.kevinsawicki.http.HttpRequest;
-import com.google.common.base.Throwables;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf.Message;
-import com.google.protobuf.Parser;
-import java.io.InputStream;
-import java.util.Arrays;
-import javax.annotation.Nullable;
-import org.sonarqube.ws.MediaTypes;
-
-import static java.net.HttpURLConnection.HTTP_CREATED;
-import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
-import static java.net.HttpURLConnection.HTTP_OK;
-
-/**
- * Not an API. Please do not use this class, except maybe for unit tests.
- */
-public class HttpRequestFactory {
-
- private static final int[] RESPONSE_SUCCESS = {HTTP_OK, HTTP_CREATED, HTTP_NO_CONTENT};
-
- private final String baseUrl;
- private String login;
- private String password;
- private String proxyHost;
- private String proxyLogin;
- private String proxyPassword;
- private int proxyPort;
- private int connectTimeoutInMilliseconds;
- private int readTimeoutInMilliseconds;
-
- public HttpRequestFactory(String baseUrl) {
- this.baseUrl = baseUrl;
- }
-
- public HttpRequestFactory setLogin(@Nullable String login) {
- this.login = login;
- return this;
- }
-
- public HttpRequestFactory setPassword(@Nullable String password) {
- this.password = password;
- return this;
- }
-
- public HttpRequestFactory setProxyHost(@Nullable String proxyHost) {
- this.proxyHost = proxyHost;
- return this;
- }
-
- public HttpRequestFactory setProxyLogin(@Nullable String proxyLogin) {
- this.proxyLogin = proxyLogin;
- return this;
- }
-
- public HttpRequestFactory setProxyPassword(@Nullable String proxyPassword) {
- this.proxyPassword = proxyPassword;
- return this;
- }
-
- public HttpRequestFactory setProxyPort(int proxyPort) {
- this.proxyPort = proxyPort;
- return this;
- }
-
- public HttpRequestFactory setConnectTimeoutInMilliseconds(int connectTimeoutInMilliseconds) {
- this.connectTimeoutInMilliseconds = connectTimeoutInMilliseconds;
- return this;
- }
-
- public HttpRequestFactory setReadTimeoutInMilliseconds(int readTimeoutInMilliseconds) {
- this.readTimeoutInMilliseconds = readTimeoutInMilliseconds;
- return this;
- }
-
- public String getBaseUrl() {
- return baseUrl;
- }
-
- public String getLogin() {
- return login;
- }
-
- public String getPassword() {
- return password;
- }
-
- public String getProxyHost() {
- return proxyHost;
- }
-
- public String getProxyLogin() {
- return proxyLogin;
- }
-
- public String getProxyPassword() {
- return proxyPassword;
- }
-
- public int getProxyPort() {
- return proxyPort;
- }
-
- public int getConnectTimeoutInMilliseconds() {
- return connectTimeoutInMilliseconds;
- }
-
- public int getReadTimeoutInMilliseconds() {
- return readTimeoutInMilliseconds;
- }
-
- public String execute(WsRequest wsRequest) {
- HttpRequest httpRequest = wsRequestToHttpRequest(wsRequest);
- return execute(httpRequest);
- }
-
- public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) {
- HttpRequest httpRequest = wsRequestToHttpRequest(wsRequest);
- InputStream response = executeWithStream(httpRequest);
- try {
- return protobufParser.parseFrom(response);
- } catch (InvalidProtocolBufferException e) {
- Throwables.propagate(e);
- }
-
- throw new IllegalStateException("Uncatched exception when parsing protobuf response");
- }
-
- private HttpRequest wsRequestToHttpRequest(WsRequest wsRequest) {
- HttpRequest httpRequest = WsRequest.Method.GET.equals(wsRequest.getMethod())
- ? HttpRequest.get(buildUrl(wsRequest.getEndpoint()), wsRequest.getParams(), true)
- : HttpRequest.post(buildUrl(wsRequest.getEndpoint()), wsRequest.getParams(), true);
- httpRequest = prepare(httpRequest);
- switch (wsRequest.getMediaType()) {
- case PROTOBUF:
- httpRequest.accept(MediaTypes.PROTOBUF);
- break;
- case JSON:
- httpRequest.accept(MediaTypes.JSON);
- break;
- case TEXT:
- httpRequest.accept(MediaTypes.TXT);
- break;
- default:
- httpRequest.accept(MediaTypes.DEFAULT);
- break;
- }
-
- return httpRequest;
- }
-
- private String buildUrl(String part) {
- StringBuilder url = new StringBuilder();
- url.append(baseUrl);
- if (!part.startsWith("/")) {
- url.append('/');
- }
- url.append(part);
- return url.toString();
- }
-
- private static String execute(HttpRequest request) {
- try {
- checkSuccess(request);
- return request.body(HttpRequest.CHARSET_UTF8);
- } catch (HttpRequest.HttpRequestException e) {
- throw new IllegalStateException("Fail to request " + request.url(), e);
- }
- }
-
- private static InputStream executeWithStream(HttpRequest request) {
- try {
- checkSuccess(request);
- return request.stream();
- } catch (HttpRequest.HttpRequestException e) {
- throw new IllegalStateException("Fail to request " + request.url(), e);
- }
- }
-
- private static void checkSuccess(HttpRequest request) {
- boolean isSuccess = Arrays.binarySearch(RESPONSE_SUCCESS, request.code()) >= 0;
- if (!isSuccess) {
- throw new HttpException(request.url().toString(), request.code(), request.body());
- }
- }
-
- private HttpRequest prepare(HttpRequest request) {
- if (proxyHost != null) {
- request.useProxy(proxyHost, proxyPort);
- if (proxyLogin != null) {
- request.proxyBasic(proxyLogin, proxyPassword);
- }
- }
- request
- .acceptGzipEncoding()
- .uncompress(true)
- .acceptJson()
- .acceptCharset(HttpRequest.CHARSET_UTF8)
- .connectTimeout(connectTimeoutInMilliseconds)
- .readTimeout(readTimeoutInMilliseconds)
- .trustAllCerts()
- .trustAllHosts();
- if (login != null) {
- request.basic(login, password);
- }
- return request;
- }
-}
--- /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;
+
+import com.squareup.okhttp.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+
+class HttpResponse implements WsResponse {
+
+ private final Response okResponse;
+
+ HttpResponse(Response okResponse) {
+ this.okResponse = okResponse;
+ }
+
+ @Override
+ public String getRequestUrl() {
+ return okResponse.request().urlString();
+ }
+
+ @Override
+ public boolean hasContent() {
+ return okResponse.code() != HTTP_NO_CONTENT;
+ }
+
+ @Override
+ public String getContentType() {
+ return okResponse.header("Content-Type");
+ }
+
+ /**
+ * Get stream of bytes
+ */
+ @Override
+ public InputStream getContentStream() {
+ try {
+ return okResponse.body().byteStream();
+ } catch (IOException e) {
+ throw fail(e);
+ }
+ }
+
+ /**
+ * Get stream of characters, decoded with the charset
+ * of the Content-Type header. If that header is either absent or lacks a
+ * charset, this will attempt to decode the response body as UTF-8.
+ */
+ @Override
+ public Reader getContentReader() {
+ try {
+ return okResponse.body().charStream();
+ } catch (IOException e) {
+ throw fail(e);
+ }
+ }
+
+ @Override
+ public String getContent() {
+ try {
+ return okResponse.body().string();
+ } catch (IOException e) {
+ throw fail(e);
+ }
+ }
+
+ private RuntimeException fail(Exception e) {
+ throw new IllegalStateException("Fail to read response of " + getRequestUrl(), e);
+ }
+}
--- /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;
+
+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;
+import org.sonarqube.ws.client.qualityprofile.QualityProfilesService;
+import org.sonarqube.ws.client.usertoken.UserTokensService;
+
+/**
+ * Entry point of the Java Client for SonarQube Web Services
+ *
+ * @since 5.3
+ */
+public class HttpWsClient implements WsClient {
+
+ private final ComputeEngineService ceWsClient;
+ private final PermissionsService permissionsService;
+ private final ComponentsService componentsService;
+ private final QualityProfilesService qualityProfilesService;
+ private final IssuesService issuesService;
+ private final UserTokensService userTokensService;
+ private final WsConnector wsConnector;
+
+ 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);
+ this.issuesService = new IssuesService(wsConnector);
+ this.userTokensService = new UserTokensService(wsConnector);
+ }
+
+ @Override
+ public WsConnector wsConnector() {
+ return wsConnector;
+ }
+
+ @Override
+ public PermissionsService permissions() {
+ return this.permissionsService;
+ }
+
+ @Override
+ public ComputeEngineService computeEngine() {
+ return ceWsClient;
+ }
+
+ @Override
+ public ComponentsService components() {
+ return componentsService;
+ }
+
+ @Override
+ public QualityProfilesService qualityProfiles() {
+ return qualityProfilesService;
+ }
+
+ @Override
+ public IssuesService issues() {
+ return issuesService;
+ }
+
+ @Override
+ public UserTokensService userTokens() {
+ return userTokensService;
+ }
+}
--- /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;
+
+import com.google.common.base.Throwables;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+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 {
+
+ private String requestUrl;
+ private byte[] content;
+ private String contentType;
+
+ @Override
+ public String getContentType() {
+ requireNonNull(contentType);
+ return contentType;
+ }
+
+ public MockWsResponse setContentType(String contentType) {
+ this.contentType = contentType;
+ return this;
+ }
+
+ public MockWsResponse setRequestUrl(String requestUrl) {
+ this.requestUrl = requestUrl;
+ return this;
+ }
+
+ public MockWsResponse setContent(InputStream is) {
+ try {
+ return setContent(IOUtils.toByteArray(is));
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ public MockWsResponse setContent(byte[] b) {
+ this.content = b;
+ return this;
+ }
+
+ public MockWsResponse setContent(String s) {
+ this.content = s.getBytes(StandardCharsets.UTF_8);
+ return this;
+ }
+
+ @Override
+ public boolean hasContent() {
+ return content != null;
+ }
+
+ @Override
+ public String getRequestUrl() {
+ requireNonNull(requestUrl);
+ return requestUrl;
+ }
+
+ @Override
+ public InputStream getContentStream() {
+ requireNonNull(content);
+ return new ByteArrayInputStream(content);
+ }
+
+ @Override
+ public Reader getContentReader() {
+ requireNonNull(content);
+ return new StringReader(new String(content, StandardCharsets.UTF_8));
+ }
+
+ @Override
+ public String getContent() {
+ requireNonNull(content);
+ return new String(content, StandardCharsets.UTF_8);
+ }
+
+ public static MockWsResponse createJson(String json) {
+ return new MockWsResponse()
+ .setContentType(MediaTypes.JSON)
+ .setContentType(json);
+ }
+}
--- /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;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @since 5.3
+ */
+public class PostRequest extends BaseRequest<PostRequest> {
+
+ private final Map<String, Part> parts = new LinkedHashMap<>();
+
+ public PostRequest(String path) {
+ super(path);
+ }
+
+ @Override
+ public Method getMethod() {
+ return Method.POST;
+ }
+
+ public PostRequest setPart(String name, Part part) {
+ this.parts.put(name, part);
+ return this;
+ }
+
+ public Map<String, Part> getParts() {
+ return parts;
+ }
+
+ public static class Part {
+ private final String mediaType;
+ private final File file;
+
+ public Part(String mediaType, File file) {
+ this.mediaType = mediaType;
+ this.file = file;
+ }
+
+ public String getMediaType() {
+ return mediaType;
+ }
+
+ public File getFile() {
+ return file;
+ }
+ }
+
+}
* 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 com.google.protobuf.Message;
-import com.google.protobuf.Parser;
-import org.sonarqube.ws.client.component.ComponentsWsClient;
-import org.sonarqube.ws.client.issue.IssuesWsClient;
-import org.sonarqube.ws.client.permission.PermissionsWsClient;
-import org.sonarqube.ws.client.qualityprofile.QualityProfilesWsClient;
-import org.sonarqube.ws.client.usertoken.UserTokensWsClient;
-
-import static org.sonarqube.ws.client.WsRequest.MediaType.PROTOBUF;
+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;
+import org.sonarqube.ws.client.qualityprofile.QualityProfilesService;
+import org.sonarqube.ws.client.usertoken.UserTokensService;
/**
- * Entry point of the Java Client for SonarQube Web Services.
- * <p/>
- * Example:
- * <pre>
- * WsClient client = new WsClient(Connector);
- * </pre>
- *
- * @since 5.2
+ * @since 5.3
*/
-public class WsClient {
-
- @VisibleForTesting
- final WsConnector wsConnector;
- private final PermissionsWsClient permissionsWsClient;
- private final ComponentsWsClient componentsWsClient;
- private final QualityProfilesWsClient qualityProfilesWsClient;
- private final IssuesWsClient issuesWsClient;
- private final UserTokensWsClient userTokensWsClient;
-
- public WsClient(WsConnector wsConnector) {
- this.wsConnector = wsConnector;
- this.permissionsWsClient = new PermissionsWsClient(this);
- this.componentsWsClient = new ComponentsWsClient(this);
- this.qualityProfilesWsClient = new QualityProfilesWsClient(this);
- this.issuesWsClient = new IssuesWsClient(this);
- userTokensWsClient = new UserTokensWsClient(this);
- }
-
- public String execute(WsRequest wsRequest) {
- return wsConnector.execute(wsRequest);
- }
+public interface WsClient {
+ ComponentsService components();
- public <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser) {
- return wsConnector.execute(wsRequest.setMediaType(PROTOBUF), protobufParser);
- }
+ ComputeEngineService computeEngine();
- public PermissionsWsClient permissionsClient() {
- return this.permissionsWsClient;
- }
+ IssuesService issues();
- public ComponentsWsClient componentsWsClient() {
- return componentsWsClient;
- }
+ PermissionsService permissions();
- public QualityProfilesWsClient qualityProfilesWsClient() {
- return qualityProfilesWsClient;
- }
+ QualityProfilesService qualityProfiles();
- public IssuesWsClient issuesWsClient() {
- return issuesWsClient;
- }
+ UserTokensService userTokens();
- public UserTokensWsClient userTokensWsClient() {
- return userTokensWsClient;
- }
+ WsConnector wsConnector();
}
package org.sonarqube.ws.client;
-import com.google.protobuf.Message;
-import com.google.protobuf.Parser;
-
+/**
+ * @since 5.3
+ */
public interface WsConnector {
- String execute(WsRequest wsRequest);
- <T extends Message> T execute(WsRequest wsRequest, Parser<T> protobufParser);
+ /**
+ * @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();
+
}
package org.sonarqube.ws.client;
-import java.util.HashMap;
import java.util.Map;
-import javax.annotation.Nullable;
-import static java.util.Objects.requireNonNull;
-import static org.sonarqube.ws.client.WsRequest.Method.GET;
-import static org.sonarqube.ws.client.WsRequest.Method.POST;
-
-public class WsRequest {
- private final Map<String, Object> params = new HashMap<>();
- private Method method = Method.GET;
- private MediaType mimeType = MediaType.JSON;
- private String endpoint;
-
- private WsRequest(String endpoint) {
- this.endpoint = endpoint;
- }
-
- public static WsRequest newPostRequest(String endpoint) {
- return new WsRequest(endpoint)
- .setMethod(POST);
- }
-
- public static WsRequest newGetRequest(String endpoint) {
- return new WsRequest(endpoint)
- .setMethod(GET);
- }
-
- public Method getMethod() {
- return method;
- }
-
- private WsRequest setMethod(Method method) {
- this.method = method;
- return this;
- }
-
- public MediaType getMediaType() {
- return mimeType;
- }
-
- public WsRequest setMediaType(MediaType type) {
- requireNonNull(type);
- this.mimeType = type;
- return this;
- }
+/**
+ * @since 5.3
+ */
+public interface WsRequest {
- public WsRequest setParam(String key, @Nullable Object value) {
- requireNonNull(key, "a WS parameter key cannot be null");
- if (value != null) {
- this.params.put(key, value);
- } else {
- this.params.remove(key);
- }
+ Method getMethod();
- return this;
- }
+ String getPath();
- public String getEndpoint() {
- return endpoint;
- }
+ String getMediaType();
- public Map<String, Object> getParams() {
- return params;
- }
+ Map<String, String> getParams();
- public enum Method {
+ enum Method {
GET, POST
}
-
- public enum MediaType {
- PROTOBUF, JSON, TEXT
- }
}
--- /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;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * @since 5.3
+ */
+public interface WsResponse {
+
+ boolean hasContent();
+
+ String getContentType();
+
+ String getRequestUrl();
+
+ InputStream getContentStream();
+
+ Reader getContentReader();
+
+ 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;
+
--- /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.component;
+
+import org.sonarqube.ws.WsComponents.SearchWsResponse;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+public class ComponentsService extends BaseService {
+
+ public ComponentsService(WsConnector wsConnector) {
+ super(wsConnector, "api/components");
+ }
+
+ public SearchWsResponse search(SearchWsRequest request) {
+ GetRequest get = new GetRequest(path("search"))
+ .setParam("qualifiers", request.getQualifiers())
+ .setParam("p", request.getPage())
+ .setParam("ps", request.getPageSize())
+ .setParam("q", request.getQuery());
+ return call(get, SearchWsResponse.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.component;
-
-import org.sonarqube.ws.WsComponents.SearchWsResponse;
-import org.sonarqube.ws.client.WsClient;
-
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-
-public class ComponentsWsClient {
- private static final String ENDPOINT = "api/components/";
- private final WsClient wsClient;
-
- public ComponentsWsClient(WsClient wsClient) {
- this.wsClient = wsClient;
- }
-
- public SearchWsResponse search(SearchWsRequest request) {
- return wsClient.execute(
- newGetRequest(action("search"))
- .setParam("qualifiers", request.getQualifiers())
- .setParam("p", request.getPage())
- .setParam("ps", request.getPageSize())
- .setParam("q", request.getQuery()),
- SearchWsResponse.parser());
- }
-
- private static String action(String action) {
- return ENDPOINT + action;
- }
-}
import java.util.List;
/**
- * @since 3.7
+ * @since 5.3
*/
public class IssueFilterParameters {
--- /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.issue;
+
+import com.google.common.base.Joiner;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonarqube.ws.Issues.SearchWsResponse;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.ACTION_PLANS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.ADDITIONAL_FIELDS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASC;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNED;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNEES;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.AUTHORS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENTS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_KEYS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_ROOTS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_ROOT_UUIDS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_UUIDS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AFTER;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AT;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_BEFORE;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_IN_LAST;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.DIRECTORIES;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.FACET_MODE;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.FILE_UUIDS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.ISSUES;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.LANGUAGES;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.MODULE_UUIDS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.ON_COMPONENT_ONLY;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.PLANNED;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECTS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECT_KEYS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECT_UUIDS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.REPORTERS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLUTIONS;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLVED;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.RULES;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.SEVERITIES;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.STATUSES;
+import static org.sonarqube.ws.client.issue.IssueFilterParameters.TAGS;
+
+public class IssuesService extends BaseService {
+ private static final Joiner LIST_TO_PARAMS_STRING = Joiner.on(",").skipNulls();
+
+ public IssuesService(WsConnector wsConnector) {
+ super(wsConnector, "api/issues");
+ }
+
+ public SearchWsResponse search(SearchWsRequest request) {
+ return call(
+ new GetRequest(path("search"))
+ .setParam(ACTION_PLANS, listToParamList(request.getActionPlans()))
+ .setParam(ADDITIONAL_FIELDS, listToParamList(request.getAdditionalFields()))
+ .setParam(ASC, request.getAsc())
+ .setParam(ASSIGNED, request.getAssigned())
+ .setParam(ASSIGNEES, listToParamList(request.getAssignees()))
+ .setParam(AUTHORS, listToParamList(request.getAuthors()))
+ .setParam(COMPONENT_KEYS, listToParamList(request.getComponentKeys()))
+ .setParam(COMPONENT_ROOT_UUIDS, listToParamList(request.getComponentRootUuids()))
+ .setParam(COMPONENT_ROOTS, listToParamList(request.getComponentRoots()))
+ .setParam(COMPONENT_UUIDS, listToParamList(request.getComponentUuids()))
+ .setParam(COMPONENTS, listToParamList(request.getComponents()))
+ .setParam(CREATED_AFTER, request.getCreatedAfter())
+ .setParam(CREATED_AT, request.getCreatedAt())
+ .setParam(CREATED_BEFORE, request.getCreatedBefore())
+ .setParam(CREATED_IN_LAST, request.getCreatedInLast())
+ .setParam(DIRECTORIES, listToParamList(request.getDirectories()))
+ .setParam(FACET_MODE, request.getFacetMode())
+ .setParam("facets", listToParamList(request.getFacets()))
+ .setParam(FILE_UUIDS, listToParamList(request.getFileUuids()))
+ .setParam(ISSUES, listToParamList(request.getIssues()))
+ .setParam(LANGUAGES, listToParamList(request.getLanguages()))
+ .setParam(MODULE_UUIDS, listToParamList(request.getModuleUuids()))
+ .setParam(ON_COMPONENT_ONLY, request.getOnComponentOnly())
+ .setParam("p", request.getPage())
+ .setParam("ps", request.getPageSize())
+ .setParam(PLANNED, request.getPlanned())
+ .setParam(PROJECT_KEYS, listToParamList(request.getProjectKeys()))
+ .setParam(PROJECT_UUIDS, listToParamList(request.getProjectUuids()))
+ .setParam(PROJECTS, listToParamList(request.getProjects()))
+ .setParam(REPORTERS, listToParamList(request.getReporters()))
+ .setParam(RESOLUTIONS, listToParamList(request.getResolutions()))
+ .setParam(RESOLVED, request.getResolved())
+ .setParam(RULES, listToParamList(request.getRules()))
+ .setParam("s", request.getSort())
+ .setParam(SEVERITIES, listToParamList(request.getSeverities()))
+ .setParam(STATUSES, listToParamList(request.getStatuses()))
+ .setParam(TAGS, listToParamList(request.getTags())),
+ SearchWsResponse.parser());
+ }
+
+ @CheckForNull
+ private static String listToParamList(@Nullable List<String> strings) {
+ return strings == null
+ ? null
+ : LIST_TO_PARAMS_STRING.join(strings);
+ }
+}
+++ /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.issue;
-
-import com.google.common.base.Joiner;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonarqube.ws.Issues.SearchWsResponse;
-import org.sonarqube.ws.client.WsClient;
-
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ACTION_PLANS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ADDITIONAL_FIELDS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASC;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNED;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNEES;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.AUTHORS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENTS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_KEYS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_ROOTS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_ROOT_UUIDS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.COMPONENT_UUIDS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AFTER;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AT;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_BEFORE;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_IN_LAST;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.DIRECTORIES;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.FACET_MODE;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.FILE_UUIDS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ISSUES;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.LANGUAGES;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.MODULE_UUIDS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.ON_COMPONENT_ONLY;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.PLANNED;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECTS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECT_KEYS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.PROJECT_UUIDS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.REPORTERS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLUTIONS;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLVED;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.RULES;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.SEVERITIES;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.STATUSES;
-import static org.sonarqube.ws.client.issue.IssueFilterParameters.TAGS;
-
-public class IssuesWsClient {
- private static final Joiner LIST_TO_PARAMS_STRING = Joiner.on(",").skipNulls();
- private final WsClient wsClient;
-
- public IssuesWsClient(WsClient wsClient) {
- this.wsClient = wsClient;
- }
-
- public SearchWsResponse search(SearchWsRequest request) {
- return wsClient.execute(
- newGetRequest(action("search"))
- .setParam(ACTION_PLANS, listToParamList(request.getActionPlans()))
- .setParam(ADDITIONAL_FIELDS, listToParamList(request.getAdditionalFields()))
- .setParam(ASC, request.getAsc())
- .setParam(ASSIGNED, request.getAssigned())
- .setParam(ASSIGNEES, listToParamList(request.getAssignees()))
- .setParam(AUTHORS, listToParamList(request.getAuthors()))
- .setParam(COMPONENT_KEYS, listToParamList(request.getComponentKeys()))
- .setParam(COMPONENT_ROOT_UUIDS, listToParamList(request.getComponentRootUuids()))
- .setParam(COMPONENT_ROOTS, listToParamList(request.getComponentRoots()))
- .setParam(COMPONENT_UUIDS, listToParamList(request.getComponentUuids()))
- .setParam(COMPONENTS, listToParamList(request.getComponents()))
- .setParam(CREATED_AFTER, request.getCreatedAfter())
- .setParam(CREATED_AT, request.getCreatedAt())
- .setParam(CREATED_BEFORE, request.getCreatedBefore())
- .setParam(CREATED_IN_LAST, request.getCreatedInLast())
- .setParam(DIRECTORIES, listToParamList(request.getDirectories()))
- .setParam(FACET_MODE, request.getFacetMode())
- .setParam("facets", listToParamList(request.getFacets()))
- .setParam(FILE_UUIDS, listToParamList(request.getFileUuids()))
- .setParam(ISSUES, listToParamList(request.getIssues()))
- .setParam(LANGUAGES, listToParamList(request.getLanguages()))
- .setParam(MODULE_UUIDS, listToParamList(request.getModuleUuids()))
- .setParam(ON_COMPONENT_ONLY, request.getOnComponentOnly())
- .setParam("p", request.getPage())
- .setParam("ps", request.getPageSize())
- .setParam(PLANNED, request.getPlanned())
- .setParam(PROJECT_KEYS, listToParamList(request.getProjectKeys()))
- .setParam(PROJECT_UUIDS, listToParamList(request.getProjectUuids()))
- .setParam(PROJECTS, listToParamList(request.getProjects()))
- .setParam(REPORTERS, listToParamList(request.getReporters()))
- .setParam(RESOLUTIONS, listToParamList(request.getResolutions()))
- .setParam(RESOLVED, request.getResolved())
- .setParam(RULES, listToParamList(request.getRules()))
- .setParam("s", request.getSort())
- .setParam(SEVERITIES, listToParamList(request.getSeverities()))
- .setParam(STATUSES, listToParamList(request.getStatuses()))
- .setParam(TAGS, listToParamList(request.getTags())),
- SearchWsResponse.parser());
- }
-
- private static String action(String action) {
- return "api/issues/" + action;
- }
-
- @CheckForNull
- private static String listToParamList(@Nullable List<String> strings) {
- return strings == null
- ? null
- : LIST_TO_PARAMS_STRING.join(strings);
- }
-}
--- /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.permission;
+
+import org.sonarqube.ws.WsPermissions;
+import org.sonarqube.ws.WsPermissions.CreateTemplateWsResponse;
+import org.sonarqube.ws.WsPermissions.SearchProjectPermissionsWsResponse;
+import org.sonarqube.ws.WsPermissions.SearchTemplatesWsResponse;
+import org.sonarqube.ws.WsPermissions.UpdateTemplateWsResponse;
+import org.sonarqube.ws.WsPermissions.UsersWsResponse;
+import org.sonarqube.ws.WsPermissions.WsSearchGlobalPermissionsResponse;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.PostRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_DESCRIPTION;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY_PATTERN;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_USER_LOGIN;
+
+public class PermissionsService extends BaseService {
+
+ public PermissionsService(WsConnector wsConnector) {
+ super(wsConnector, PermissionsWsParameters.CONTROLLER);
+ }
+
+ public WsPermissions.WsGroupsResponse groups(GroupsWsRequest request) {
+ GetRequest get = new GetRequest(path("groups"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+ .setParam("p", request.getPage())
+ .setParam("ps", request.getPageSize())
+ .setParam("selected", request.getSelected())
+ .setParam("q", request.getQuery());
+ return call(get, WsPermissions.WsGroupsResponse.parser());
+ }
+
+ public void addGroup(AddGroupWsRequest request) {
+ call(new PostRequest(path("add_group"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+ .setParam(PARAM_GROUP_ID, request.getGroupId())
+ .setParam(PARAM_GROUP_NAME, request.getGroupName()));
+ }
+
+ public void addGroupToTemplate(AddGroupToTemplateWsRequest request) {
+ call(new PostRequest(path("add_group_to_template"))
+ .setParam(PARAM_GROUP_ID, request.getGroupId())
+ .setParam(PARAM_GROUP_NAME, request.getGroupName())
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
+ .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
+ }
+
+ public void addUser(AddUserWsRequest request) {
+ call(new PostRequest(path("add_user"))
+ .setParam(PARAM_USER_LOGIN, request.getLogin())
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey()));
+ }
+
+ public void addUserToTemplate(AddUserToTemplateWsRequest request) {
+ call(new PostRequest(path("add_user_to_template"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_USER_LOGIN, request.getLogin())
+ .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
+ .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
+ }
+
+ public void applyTemplate(ApplyTemplateWsRequest request) {
+ call(new PostRequest(path("apply_template"))
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+ .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
+ .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
+ }
+
+ public CreateTemplateWsResponse createTemplate(CreateTemplateWsRequest request) {
+ PostRequest post = new PostRequest(path("create_template"))
+ .setParam(PARAM_NAME, request.getName())
+ .setParam(PARAM_DESCRIPTION, request.getDescription())
+ .setParam(PARAM_PROJECT_KEY_PATTERN, request.getProjectKeyPattern());
+ return call(post, CreateTemplateWsResponse.parser());
+ }
+
+ public void deleteTemplate(DeleteTemplateWsRequest request) {
+ call(new PostRequest(path("delete_template"))
+ .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
+ .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
+ }
+
+ public void removeGroup(RemoveGroupWsRequest request) {
+ call(new PostRequest(path("remove_group"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_GROUP_ID, request.getGroupId())
+ .setParam(PARAM_GROUP_NAME, request.getGroupName())
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey()));
+ }
+
+ public void removeGroupFromTemplate(RemoveGroupFromTemplateWsRequest request) {
+ call(new PostRequest(path("remove_group_from_template"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_GROUP_ID, request.getGroupId())
+ .setParam(PARAM_GROUP_NAME, request.getGroupName())
+ .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
+ .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
+ }
+
+ public void removeUser(RemoveUserWsRequest request) {
+ call(new PostRequest(path("remove_user"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_USER_LOGIN, request.getLogin())
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey()));
+ }
+
+ public void removeUserFromTemplate(RemoveUserFromTemplateWsRequest request) {
+ call(new PostRequest(path("remove_user_from_template"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_USER_LOGIN, request.getLogin())
+ .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
+ .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
+ }
+
+ public WsSearchGlobalPermissionsResponse searchGlobalPermissions() {
+ GetRequest get = new GetRequest(path("search_global_permissions"));
+ return call(get, WsSearchGlobalPermissionsResponse.parser());
+ }
+
+ public SearchProjectPermissionsWsResponse searchProjectPermissions(SearchProjectPermissionsWsRequest request) {
+ GetRequest get = new GetRequest(path("search_project_permissions"))
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+ .setParam(PARAM_QUALIFIER, request.getQualifier())
+ .setParam("p", request.getPage())
+ .setParam("ps", request.getPageSize())
+ .setParam("q", request.getQuery());
+ return call(get, SearchProjectPermissionsWsResponse.parser());
+ }
+
+ public SearchTemplatesWsResponse searchTemplates(SearchTemplatesWsRequest request) {
+ GetRequest get = new GetRequest(path("search_templates"))
+ .setParam("q", request.getQuery());
+ return call(get, SearchTemplatesWsResponse.parser());
+ }
+
+ public void setDefaultTemplate(SetDefaultTemplateWsRequest request) {
+ call(new PostRequest(path("set_default_template"))
+ .setParam(PARAM_QUALIFIER, request.getQualifier())
+ .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
+ .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
+ }
+
+ public UpdateTemplateWsResponse updateTemplate(UpdateTemplateWsRequest request) {
+ return call(new PostRequest(path("update_template"))
+ .setParam(PARAM_DESCRIPTION, request.getDescription())
+ .setParam(PARAM_ID, request.getId())
+ .setParam(PARAM_NAME, request.getName())
+ .setParam(PARAM_PROJECT_KEY_PATTERN, request.getProjectKeyPattern()), UpdateTemplateWsResponse.parser());
+ }
+
+ public UsersWsResponse users(UsersWsRequest request) {
+ return call(new GetRequest(path("users"))
+ .setParam(PARAM_PERMISSION, request.getPermission())
+ .setParam(PARAM_PROJECT_ID, request.getProjectId())
+ .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+ .setParam("selected", request.getSelected())
+ .setParam("p", request.getPage())
+ .setParam("ps", request.getPageSize())
+ .setParam("q", request.getQuery()), UsersWsResponse.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.permission;
-
-import org.sonarqube.ws.WsPermissions;
-import org.sonarqube.ws.WsPermissions.CreateTemplateWsResponse;
-import org.sonarqube.ws.WsPermissions.SearchProjectPermissionsWsResponse;
-import org.sonarqube.ws.WsPermissions.SearchTemplatesWsResponse;
-import org.sonarqube.ws.WsPermissions.UpdateTemplateWsResponse;
-import org.sonarqube.ws.WsPermissions.UsersWsResponse;
-import org.sonarqube.ws.WsPermissions.WsSearchGlobalPermissionsResponse;
-import org.sonarqube.ws.client.WsClient;
-
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-import static org.sonarqube.ws.client.WsRequest.newPostRequest;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_DESCRIPTION;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_ID;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ID;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_NAME;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY_PATTERN;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME;
-import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_USER_LOGIN;
-
-public class PermissionsWsClient {
- private final WsClient wsClient;
-
- public PermissionsWsClient(WsClient wsClient) {
- this.wsClient = wsClient;
- }
-
- public WsPermissions.WsGroupsResponse groups(GroupsWsRequest request) {
- return wsClient.execute(newGetRequest(action("groups"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
- .setParam("p", request.getPage())
- .setParam("ps", request.getPageSize())
- .setParam("selected", request.getSelected())
- .setParam("q", request.getQuery()),
- WsPermissions.WsGroupsResponse.parser());
- }
-
- public void addGroup(AddGroupWsRequest request) {
- wsClient.execute(newPostRequest(action("add_group"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
- .setParam(PARAM_GROUP_ID, request.getGroupId())
- .setParam(PARAM_GROUP_NAME, request.getGroupName()));
- }
-
- public void addGroupToTemplate(AddGroupToTemplateWsRequest request) {
- wsClient.execute(newPostRequest(action("add_group_to_template"))
- .setParam(PARAM_GROUP_ID, request.getGroupId())
- .setParam(PARAM_GROUP_NAME, request.getGroupName())
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
- .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
- }
-
- public void addUser(AddUserWsRequest request) {
- wsClient.execute(newPostRequest(action("add_user"))
- .setParam(PARAM_USER_LOGIN, request.getLogin())
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey()));
- }
-
- public void addUserToTemplate(AddUserToTemplateWsRequest request) {
- wsClient.execute(newPostRequest(action("add_user_to_template"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_USER_LOGIN, request.getLogin())
- .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
- .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
- }
-
- public void applyTemplate(ApplyTemplateWsRequest request) {
- wsClient.execute(newPostRequest(action("apply_template"))
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
- .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
- .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
- }
-
- public CreateTemplateWsResponse createTemplate(CreateTemplateWsRequest request) {
- return wsClient.execute(newPostRequest(
- action("create_template"))
- .setParam(PARAM_NAME, request.getName())
- .setParam(PARAM_DESCRIPTION, request.getDescription())
- .setParam(PARAM_PROJECT_KEY_PATTERN, request.getProjectKeyPattern()),
- CreateTemplateWsResponse.parser());
- }
-
- public void deleteTemplate(DeleteTemplateWsRequest request) {
- wsClient.execute(newPostRequest(action("delete_template"))
- .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
- .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
- }
-
- public void removeGroup(RemoveGroupWsRequest request) {
- wsClient.execute(newPostRequest(action("remove_group"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_GROUP_ID, request.getGroupId())
- .setParam(PARAM_GROUP_NAME, request.getGroupName())
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey()));
- }
-
- public void removeGroupFromTemplate(RemoveGroupFromTemplateWsRequest request) {
- wsClient.execute(newPostRequest(action("remove_group_from_template"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_GROUP_ID, request.getGroupId())
- .setParam(PARAM_GROUP_NAME, request.getGroupName())
- .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
- .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
- }
-
- public void removeUser(RemoveUserWsRequest request) {
- wsClient.execute(newPostRequest(action("remove_user"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_USER_LOGIN, request.getLogin())
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey()));
- }
-
- public void removeUserFromTemplate(RemoveUserFromTemplateWsRequest request) {
- wsClient.execute(newPostRequest(action("remove_user_from_template"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_USER_LOGIN, request.getLogin())
- .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
- .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
- }
-
- public WsSearchGlobalPermissionsResponse searchGlobalPermissions() {
- return wsClient.execute(
- newGetRequest(action("search_global_permissions")),
- WsSearchGlobalPermissionsResponse.parser());
- }
-
- public SearchProjectPermissionsWsResponse searchProjectPermissions(SearchProjectPermissionsWsRequest request) {
- return wsClient.execute(
- newGetRequest(action("search_project_permissions"))
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
- .setParam(PARAM_QUALIFIER, request.getQualifier())
- .setParam("p", request.getPage())
- .setParam("ps", request.getPageSize())
- .setParam("q", request.getQuery()),
- SearchProjectPermissionsWsResponse.parser());
- }
-
- public SearchTemplatesWsResponse searchTemplates(SearchTemplatesWsRequest request) {
- return wsClient.execute(
- newGetRequest(action("search_templates"))
- .setParam("q", request.getQuery()),
- SearchTemplatesWsResponse.parser());
- }
-
- public void setDefaultTemplate(SetDefaultTemplateWsRequest request) {
- wsClient.execute(
- newPostRequest(action("set_default_template"))
- .setParam(PARAM_QUALIFIER, request.getQualifier())
- .setParam(PARAM_TEMPLATE_ID, request.getTemplateId())
- .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()));
- }
-
- public UpdateTemplateWsResponse updateTemplate(UpdateTemplateWsRequest request) {
- return wsClient.execute(
- newPostRequest(action("update_template"))
- .setParam(PARAM_DESCRIPTION, request.getDescription())
- .setParam(PARAM_ID, request.getId())
- .setParam(PARAM_NAME, request.getName())
- .setParam(PARAM_PROJECT_KEY_PATTERN, request.getProjectKeyPattern()),
- UpdateTemplateWsResponse.parser());
- }
-
- public UsersWsResponse users(UsersWsRequest request) {
- return wsClient.execute(
- newGetRequest(action("users"))
- .setParam(PARAM_PERMISSION, request.getPermission())
- .setParam(PARAM_PROJECT_ID, request.getProjectId())
- .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
- .setParam("selected", request.getSelected())
- .setParam("p", request.getPage())
- .setParam("ps", request.getPageSize())
- .setParam("q", request.getQuery()),
- UsersWsResponse.parser());
- }
-
- private static String action(String action) {
- return PermissionsWsParameters.ENDPOINT + "/" + action;
- }
-}
package org.sonarqube.ws.client.permission;
public class PermissionsWsParameters {
- public static final String ENDPOINT = "api/permissions";
+ public static final String CONTROLLER = "api/permissions";
public static final String PARAM_PERMISSION = "permission";
public static final String PARAM_GROUP_NAME = "groupName";
--- /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.qualityprofile;
+
+import org.sonarqube.ws.QualityProfiles.SearchWsResponse;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+public class QualityProfilesService extends BaseService {
+
+ public QualityProfilesService(WsConnector wsConnector) {
+ super(wsConnector, "api/qualityprofiles");
+ }
+
+ public SearchWsResponse search(SearchWsRequest request) {
+ return call(
+ new GetRequest(path("search"))
+ .setParam("defaults", request.getDefaults())
+ .setParam("language", request.getLanguage())
+ .setParam("profileName", request.getProfileName())
+ .setParam("projectKey", request.getProjectKey()),
+ SearchWsResponse.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.qualityprofile;
-
-import org.sonarqube.ws.QualityProfiles.SearchWsResponse;
-import org.sonarqube.ws.client.WsClient;
-
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-
-public class QualityProfilesWsClient {
- private final WsClient wsClient;
-
- public QualityProfilesWsClient(WsClient wsClient) {
- this.wsClient = wsClient;
- }
-
- public SearchWsResponse search(SearchWsRequest request) {
- return wsClient.execute(
- newGetRequest(action("search"))
- .setParam("defaults", request.getDefaults())
- .setParam("language", request.getLanguage())
- .setParam("profileName", request.getProfileName())
- .setParam("projectKey", request.getProjectKey()),
- SearchWsResponse.parser());
- }
-
- private static String action(String action) {
- return "api/qualityprofiles/" + action;
- }
-}
--- /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.usertoken;
+
+import org.sonarqube.ws.WsUserTokens.GenerateWsResponse;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.PostRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.ACTION_GENERATE;
+import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.CONTROLLER;
+import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.PARAM_LOGIN;
+import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.PARAM_NAME;
+
+public class UserTokensService extends BaseService {
+
+ public UserTokensService(WsConnector wsConnector) {
+ super(wsConnector, CONTROLLER);
+ }
+
+ public GenerateWsResponse generate(GenerateWsRequest request) {
+ return call(
+ new PostRequest(path(ACTION_GENERATE))
+ .setParam(PARAM_LOGIN, request.getLogin())
+ .setParam(PARAM_NAME, request.getName()),
+ GenerateWsResponse.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.usertoken;
-
-import org.sonarqube.ws.WsComponents.SearchWsResponse;
-import org.sonarqube.ws.WsUserTokens.GenerateWsResponse;
-import org.sonarqube.ws.client.WsClient;
-
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-import static org.sonarqube.ws.client.WsRequest.newPostRequest;
-import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.ACTION_GENERATE;
-import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.ACTION_REVOKE;
-import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.ACTION_SEARCH;
-import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.PARAM_LOGIN;
-import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.PARAM_NAME;
-import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.USER_TOKENS_ENDPOINT;
-
-public class UserTokensWsClient {
- private static final String SLASH = "/";
- private final WsClient wsClient;
-
- public UserTokensWsClient(WsClient wsClient) {
- this.wsClient = wsClient;
- }
-
- public GenerateWsResponse generate(GenerateWsRequest request) {
- return wsClient.execute(
- newPostRequest(action(ACTION_GENERATE))
- .setParam(PARAM_LOGIN, request.getLogin())
- .setParam(PARAM_NAME, request.getName()),
- GenerateWsResponse.parser());
- }
-
- public void revoke(RevokeWsRequest request) {
- wsClient.execute(
- newPostRequest(action(ACTION_REVOKE))
- .setParam(PARAM_LOGIN, request.getLogin())
- .setParam(PARAM_NAME, request.getName()));
- }
-
- public SearchWsResponse search(SearchWsRequest request) {
- return wsClient.execute(
- newGetRequest(action(ACTION_SEARCH))
- .setParam(PARAM_LOGIN, request.getLogin()),
- SearchWsResponse.parser()
- );
- }
-
- private static String action(String action) {
- return USER_TOKENS_ENDPOINT + SLASH + action;
- }
-}
package org.sonarqube.ws.client.usertoken;
public class UserTokensWsParameters {
- public static final String USER_TOKENS_ENDPOINT = "api/user_tokens";
+ public static final String CONTROLLER = "api/user_tokens";
public static final String ACTION_GENERATE = "generate";
public static final String ACTION_REVOKE = "revoke";
public static final String ACTION_SEARCH = "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.sonarqube.ws.client;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonarqube.ws.MediaTypes;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.data.MapEntry.entry;
+
+public class BaseRequestTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ FakeRequest underTest = new FakeRequest("api/foo");
+
+ @Test
+ public void test_defaults() {
+ assertThat(underTest.getMethod()).isEqualTo(WsRequest.Method.GET);
+ assertThat(underTest.getParams()).isEmpty();
+ assertThat(underTest.getMediaType()).isEqualTo(MediaTypes.JSON);
+ assertThat(underTest.getPath()).isEqualTo("api/foo");
+ }
+
+ @Test
+ public void setMediaType() {
+ underTest.setMediaType(MediaTypes.PROTOBUF);
+ assertThat(underTest.getMediaType()).isEqualTo(MediaTypes.PROTOBUF);
+ }
+
+ @Test
+ public void keep_order_of_params() {
+ assertThat(underTest.getParams()).isEmpty();
+
+ underTest.setParam("keyB", "b");
+ assertThat(underTest.getParams()).containsExactly(entry("keyB", "b"));
+
+ underTest.setParam("keyA", "a");
+ assertThat(underTest.getParams()).containsExactly(entry("keyB", "b"), entry("keyA", "a"));
+ }
+
+ @Test
+ public void null_param_value() {
+ underTest.setParam("key", null);
+ assertThat(underTest.getParams()).isEmpty();
+ }
+
+ @Test
+ public void fail_if_null_param_key() {
+ expectedException.expect(IllegalArgumentException.class);
+ underTest.setParam(null, "val");
+ }
+
+ private static class FakeRequest extends BaseRequest<FakeRequest> {
+ FakeRequest(String path) {
+ super(path);
+ }
+
+ @Override
+ public Method getMethod() {
+ return Method.GET;
+ }
+ }
+}
--- /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;
+
+import java.io.IOException;
+import org.junit.Test;
+import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.Testing;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class BaseServiceTest {
+
+ WsConnector wsConnector = mock(WsConnector.class);
+
+ @Test
+ public void test_call() throws Exception {
+ new BaseService(wsConnector, "api/issues") {
+
+ public void test() throws IOException {
+ GetRequest get = new GetRequest(path("issue")).setMediaType(MediaTypes.JSON);
+ when(wsConnector.call(get)).thenReturn(new MockWsResponse().setContent("ok"));
+
+ WsResponse response = call(get);
+
+ assertThat(response.getContent()).isEqualTo("ok");
+ }
+
+ }.test();
+ }
+
+ @Test
+ public void call_and_convert_protobuf() {
+ new BaseService(wsConnector, "api/issues") {
+
+ public void test() {
+ GetRequest get = new GetRequest(path("issue")).setParam("key", "ABC");
+ when(wsConnector.call(get)).thenReturn(newProtobufFakeResponse());
+
+ Testing.Fake message = call(get, Testing.Fake.parser());
+
+ assertThat(message.getLabel()).isEqualTo("ok");
+ assertThat(get.getPath()).isEqualTo("api/issues/issue");
+ // media type automatically set to protobuf
+ assertThat(get.getMediaType()).isEqualTo(MediaTypes.PROTOBUF);
+ }
+
+ }.test();
+ }
+
+ @Test
+ public void fail_to_parse_protobuf_response() {
+ new BaseService(wsConnector, "api/issues") {
+
+ public void test() {
+ GetRequest get = new GetRequest(path("issue")).setParam("key", "ABC");
+ when(wsConnector.call(get)).thenReturn(MockWsResponse.createJson("{}").setRequestUrl("http://local/api/issues/issue?key=ABC"));
+
+ try {
+ call(get, Testing.Fake.parser());
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e).hasMessage("Fail to parse protobuf response of http://local/api/issues/issue?key=ABC");
+ }
+ }
+ }.test();
+ }
+
+ private static WsResponse newProtobufFakeResponse() {
+ Testing.Fake message = Testing.Fake.newBuilder().setLabel("ok").build();
+ return new MockWsResponse().setContent(message.toByteArray());
+ }
+}
--- /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;
+
+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;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonarqube.ws.MediaTypes;
+
+import static com.squareup.okhttp.Credentials.basic;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+public class HttpConnectorTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ MockWebServer server;
+ String serverUrl;
+
+ @Before
+ public void setUp() throws Exception {
+ server = new MockWebServer();
+ server.start();
+ serverUrl = server.url("").url().toString();
+ }
+
+ @Test
+ public void test_default_settings() throws Exception {
+ answerHelloWorld();
+ HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ assertThat(underTest.baseUrl()).isEqualTo(serverUrl);
+ GetRequest request = new GetRequest("api/issues/search").setMediaType(MediaTypes.PROTOBUF);
+ WsResponse response = underTest.call(request);
+
+ // verify default timeouts on client
+ assertThat(underTest.okHttpClient().getConnectTimeout()).isEqualTo(HttpConnector.DEFAULT_CONNECT_TIMEOUT_MILLISECONDS);
+ assertThat(underTest.okHttpClient().getReadTimeout()).isEqualTo(HttpConnector.DEFAULT_READ_TIMEOUT_MILLISECONDS);
+
+ // verify response
+ assertThat(response.hasContent()).isTrue();
+ assertThat(response.getContent()).isEqualTo("hello, world!");
+
+ // verify the request received by server
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getMethod()).isEqualTo("GET");
+ assertThat(recordedRequest.getPath()).isEqualTo("/api/issues/search");
+ assertThat(recordedRequest.getHeader("Accept")).isEqualTo(MediaTypes.PROTOBUF);
+ assertThat(recordedRequest.getHeader("Accept-Charset")).isEqualTo("UTF-8");
+ assertThat(recordedRequest.getHeader("User-Agent")).startsWith("okhttp/");
+ // compression is handled by OkHttp
+ assertThat(recordedRequest.getHeader("Accept-Encoding")).isEqualTo("gzip");
+ }
+
+ @Test
+ public void use_basic_authentication() throws Exception {
+ answerHelloWorld();
+ HttpConnector underTest = new HttpConnector.Builder()
+ .url(serverUrl)
+ .credentials("theLogin", "thePassword")
+ .build();
+
+ GetRequest request = new GetRequest("api/issues/search");
+ underTest.call(request);
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("Authorization")).isEqualTo(basic("theLogin", "thePassword"));
+ }
+
+ @Test
+ public void use_basic_authentication_with_null_password() throws Exception {
+ answerHelloWorld();
+ HttpConnector underTest = new HttpConnector.Builder()
+ .url(serverUrl)
+ .credentials("theLogin", null)
+ .build();
+
+ GetRequest request = new GetRequest("api/issues/search");
+ underTest.call(request);
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("Authorization")).isEqualTo(basic("theLogin", ""));
+ }
+
+ /**
+ * Access token replaces the couple {login,password} and is sent through
+ * the login field
+ */
+ @Test
+ public void use_access_token() throws Exception {
+ answerHelloWorld();
+ HttpConnector underTest = new HttpConnector.Builder()
+ .url(serverUrl)
+ .token("theToken")
+ .build();
+
+ GetRequest request = new GetRequest("api/issues/search");
+ underTest.call(request);
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("Authorization")).isEqualTo(basic("theToken", ""));
+ }
+
+ @Test
+ public void use_proxy_authentication() throws Exception {
+ answerHelloWorld();
+ HttpConnector underTest = new HttpConnector.Builder()
+ .url(serverUrl)
+ .proxyCredentials("theProxyLogin", "theProxyPassword")
+ .build();
+
+ GetRequest request = new GetRequest("api/issues/search");
+ underTest.call(request);
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("Proxy-Authorization")).isEqualTo(basic("theProxyLogin", "theProxyPassword"));
+ }
+
+ @Test
+ public void override_timeouts() {
+ HttpConnector underTest = new HttpConnector.Builder()
+ .url(serverUrl)
+ .readTimeoutMilliseconds(42)
+ .connectTimeoutMilliseconds(74)
+ .build();
+
+ assertThat(underTest.okHttpClient().getReadTimeout()).isEqualTo(42);
+ assertThat(underTest.okHttpClient().getConnectTimeout()).isEqualTo(74);
+ }
+
+ @Test
+ public void send_user_agent() throws Exception {
+ answerHelloWorld();
+ HttpConnector underTest = new HttpConnector.Builder()
+ .url(serverUrl)
+ .userAgent("Maven Plugin/2.3")
+ .build();
+
+ underTest.call(new GetRequest("api/issues/search"));
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("User-Agent")).isEqualTo("Maven Plugin/2.3");
+ }
+
+ @Test
+ public void fail_if_unknown_implementation_of_request() {
+ HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ try {
+ underTest.call(mock(WsRequest.class));
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessageContaining("Unsupported implementation: ");
+ }
+ }
+
+ @Test
+ public void send_post_request() throws Exception {
+ answerHelloWorld();
+ PostRequest request = new PostRequest("api/issues/search")
+ .setParam("severity", "MAJOR")
+ .setMediaType(MediaTypes.PROTOBUF);
+
+ HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ WsResponse response = underTest.call(request);
+
+ // verify response
+ assertThat(response.hasContent()).isTrue();
+ assertThat(response.getContent()).isEqualTo("hello, world!");
+
+ // verify the request received by server
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getMethod()).isEqualTo("POST");
+ assertThat(recordedRequest.getPath()).isEqualTo("/api/issues/search?severity=MAJOR");
+ }
+
+ @Test
+ public void upload_file() throws Exception {
+ answerHelloWorld();
+ File reportFile = temp.newFile();
+ FileUtils.write(reportFile, "the report content");
+ PostRequest request = new PostRequest("api/report/upload")
+ .setParam("project", "theKey")
+ .setPart("report", new PostRequest.Part(MediaTypes.TXT, reportFile))
+ .setMediaType(MediaTypes.PROTOBUF);
+
+ HttpConnector underTest = new HttpConnector.Builder().url(serverUrl).build();
+ WsResponse response = underTest.call(request);
+
+ assertThat(response.hasContent()).isTrue();
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getMethod()).isEqualTo("POST");
+ assertThat(recordedRequest.getPath()).isEqualTo("/api/report/upload?project=theKey");
+ String body = IOUtils.toString(recordedRequest.getBody().inputStream());
+ assertThat(body)
+ .contains("Content-Disposition: form-data; name=\"report\"")
+ .contains("Content-Type: text/plain")
+ .contains("the report content");
+ }
+
+ @Test
+ 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();
+
+ 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();
+ }
+
+ @Test
+ public void support_base_url_ending_with_slash() throws Exception {
+ assertThat(serverUrl).endsWith("/");
+ HttpConnector underTest = new HttpConnector.Builder().url(StringUtils.removeEnd(serverUrl, "/")).build();
+ GetRequest request = new GetRequest("api/issues/search");
+
+ answerHelloWorld();
+ WsResponse response = underTest.call(request);
+
+ assertThat(response.hasContent()).isTrue();
+ }
+
+ @Test
+ public void support_base_url_with_context() {
+ // just to be sure
+ assertThat(serverUrl).endsWith("/");
+ HttpConnector underTest = new HttpConnector.Builder().url(serverUrl + "sonar").build();
+
+ GetRequest request = new GetRequest("api/issues/search");
+ answerHelloWorld();
+ assertThat(underTest.call(request).getRequestUrl()).isEqualTo(serverUrl + "sonar/api/issues/search");
+
+ request = new GetRequest("/api/issues/search");
+ answerHelloWorld();
+ assertThat(underTest.call(request).getRequestUrl()).isEqualTo(serverUrl + "sonar/api/issues/search");
+ }
+
+ private void answerHelloWorld() {
+ server.enqueue(new MockResponse().setBody("hello, world!"));
+ }
+}
@Test
public void test_exception() throws Exception {
HttpException exception = new HttpException("http://localhost:9000/api/search", 500, "Not found");
- assertThat(exception.status()).isEqualTo(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");
}
+++ /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;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-
-public class HttpRequestFactoryTest {
- @Rule
- public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor();
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Test
- public void test_get() {
- httpServer.stubStatusCode(200).stubResponseBody("{'issues': []}");
-
- HttpRequestFactory factory = new HttpRequestFactory(httpServer.url());
- String json = factory.execute(newGetRequest("/api/issues"));
-
- assertThat(json).isEqualTo("{'issues': []}");
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues");
- }
-
- @Test
- public void should_throw_illegal_state_exc_if_connect_exception() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Fail to request http://localhost:1/api/issues");
-
- HttpRequestFactory factory = new HttpRequestFactory("http://localhost:1");
- factory.execute(newGetRequest("/api/issues"));
- }
-
- @Test
- public void test_authentication() {
- httpServer.stubStatusCode(200).stubResponseBody("{}");
-
- HttpRequestFactory factory = new HttpRequestFactory(httpServer.url()).setLogin("karadoc").setPassword("legrascestlavie");
- String json = factory.execute(newGetRequest("/api/issues"));
-
- assertThat(json).isEqualTo("{}");
- assertThat(httpServer.requestedPath()).isEqualTo("/api/issues");
- assertThat(httpServer.requestHeaders().get("Authorization")).isEqualTo("Basic a2FyYWRvYzpsZWdyYXNjZXN0bGF2aWU=");
- }
-
- @Test
- public void test_proxy() throws Exception {
- expectedException.expect(IllegalStateException.class);
-
- HttpRequestFactory factory = new HttpRequestFactory(httpServer.url())
- .setProxyHost("localhost").setProxyPort(1)
- .setProxyLogin("john").setProxyPassword("smith");
- factory.execute(newGetRequest("/api/issues"));
- }
-
- @Test
- public void beginning_slash_is_optional() throws Exception {
- HttpRequestFactory factory = new HttpRequestFactory(httpServer.url());
- factory.execute(newGetRequest("api/foo"));
- assertThat(httpServer.requestedPath()).isEqualTo("/api/foo");
-
- factory.execute(newGetRequest("/api/bar"));
- assertThat(httpServer.requestedPath()).isEqualTo("/api/bar");
- }
-}
+++ /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;
-
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-
-import static org.apache.commons.io.IOUtils.write;
-
-public class MockHttpServer {
- private Server server;
- private String responseBody;
- private byte[] binaryResponseBody;
- private int responseStatus = HttpURLConnection.HTTP_OK;
- private String requestPath;
- private Map requestHeaders = new HashMap(), requestParams = new HashMap();
- private String contentType;
-
- public void start() throws Exception {
- // 0 is random available port
- server = new Server(0);
- server.setHandler(getMockHandler());
- server.start();
- }
-
- public Handler getMockHandler() {
- Handler handler = new AbstractHandler() {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException, ServletException {
- requestPath = baseRequest.getUri().toString();
- requestHeaders.clear();
- Enumeration names = baseRequest.getHeaderNames();
- while (names.hasMoreElements()) {
- String headerName = (String) names.nextElement();
- requestHeaders.put(headerName, baseRequest.getHeader(headerName));
- }
- requestParams.clear();
- names = baseRequest.getParameterNames();
- while (names.hasMoreElements()) {
- String headerName = (String) names.nextElement();
- requestParams.put(headerName, baseRequest.getParameter(headerName));
- }
- response.setStatus(responseStatus);
- response.setContentType("application/json;charset=utf-8");
- if (responseBody != null) {
- write(responseBody, response.getOutputStream());
- } else {
- write(binaryResponseBody, response.getOutputStream());
- }
- baseRequest.setHandled(true);
- }
- };
- return handler;
- }
-
- public void stop() {
- try {
- if (server != null) {
- server.stop();
- }
- } catch (Exception e) {
- throw new IllegalStateException("Fail to stop HTTP server", e);
- }
- }
-
- public MockHttpServer doReturnBody(String responseBody) {
- this.responseBody = responseBody;
- return this;
- }
-
- public MockHttpServer doReturnBody(byte[] responseBody) {
- this.binaryResponseBody = responseBody;
- return this;
- }
-
- public MockHttpServer doReturnStatus(int status) {
- this.responseStatus = status;
- return this;
- }
-
- public MockHttpServer doReturnContentType(String contentType) {
- this.contentType = contentType;
- return this;
- }
-
- public String requestPath() {
- return requestPath;
- }
-
- public Map requestHeaders() {
- return requestHeaders;
- }
-
- public Map requestParams() {
- return requestParams;
- }
-
- public int getPort() {
- return server.getConnectors()[0].getLocalPort();
- }
-}
+++ /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;
-
-import org.junit.rules.ExternalResource;
-
-import java.util.Map;
-
-public final class MockHttpServerInterceptor extends ExternalResource {
-
- private MockHttpServer server;
-
- @Override
- protected final void before() throws Throwable {
- server = new MockHttpServer();
- server.start();
- }
-
- @Override
- protected void after() {
- server.stop();
- }
-
- public MockHttpServerInterceptor stubResponseBody(String body) {
- server.doReturnBody(body);
- return this;
- }
-
- public MockHttpServerInterceptor stubStatusCode(int status) {
- server.doReturnStatus(status);
- return this;
- }
-
- public String requestedPath() {
- return server.requestPath();
- }
-
- public Map requestHeaders() {
- return server.requestHeaders();
- }
-
- public Map requestParams() {
- return server.requestParams();
- }
-
- public int port() {
- return server.getPort();
- }
-
- public String url() {
- return "http://localhost:" + port();
- }
-}
--- /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;
+
+import java.io.File;
+import java.io.IOException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonarqube.ws.MediaTypes;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PostRequestTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void post_is_post() {
+ PostRequest request = new PostRequest("api/issues/search");
+ assertThat(request.getMethod()).isEqualTo(WsRequest.Method.POST);
+ }
+
+ @Test
+ public void empty_parts_and_params_by_default() {
+ PostRequest request = new PostRequest("api/issues/search");
+ assertThat(request.getParts()).isEmpty();
+ assertThat(request.getParams()).isEmpty();
+ }
+
+ @Test
+ public void add_part() throws IOException {
+ PostRequest request = new PostRequest("api/issues/search");
+ File reportFile = temp.newFile();
+ request.setPart("report", new PostRequest.Part(MediaTypes.JSON, reportFile));
+
+ assertThat(request.getParts()).hasSize(1);
+ PostRequest.Part part = request.getParts().get("report");
+ assertThat(part.getMediaType()).isEqualTo(MediaTypes.JSON);
+ assertThat(part.getFile()).isSameAs(reportFile);
+ }
+}
+++ /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;
-
-import com.google.common.net.HttpHeaders;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonarqube.ws.MediaTypes;
-import org.sonarqube.ws.WsComponents;
-
-import static java.net.HttpURLConnection.HTTP_OK;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonarqube.ws.client.HttpConnector.newDefaultHttpConnector;
-import static org.sonarqube.ws.client.HttpConnector.newHttpConnector;
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-
-public class WsClientTest {
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- MockHttpServer server;
-
- WsClient underTest;
-
- @Before
- public void setUp() throws Exception {
- server = new MockHttpServer();
- server.start();
-
- underTest = new WsClient(newDefaultHttpConnector("http://localhost:" + server.getPort()));
- }
-
- @After
- public void stopServer() {
- if (server != null) {
- server.stop();
- }
- }
-
- @Test
- public void return_protobuf_response() throws Exception {
- server.doReturnBody(
- WsComponents.SearchWsResponse
- .newBuilder()
- .addComponents(WsComponents.SearchWsResponse.Component.getDefaultInstance())
- .build()
- .toByteArray());
- server.doReturnStatus(HTTP_OK);
- server.doReturnContentType(MediaTypes.PROTOBUF);
-
- WsComponents.SearchWsResponse response = underTest.execute(
- newGetRequest("api/components/search")
- .setMediaType(WsRequest.MediaType.PROTOBUF),
- WsComponents.SearchWsResponse.parser());
-
- assertThat(response.getComponentsCount()).isEqualTo(1);
- assertThat(server.requestHeaders().get(HttpHeaders.ACCEPT))
- .isEqualTo(MediaTypes.PROTOBUF);
- }
-
- @Test
- public void return_json_response() throws Exception {
- String expectedResponse = "{\"key\":value}";
- server.doReturnBody(expectedResponse);
- server.doReturnStatus(HTTP_OK);
- server.doReturnContentType(MediaTypes.JSON);
-
- String response = underTest.execute(newGetRequest("api/components/search"));
-
- assertThat(response).isEqualTo(expectedResponse);
- assertThat(server.requestHeaders().get(HttpHeaders.ACCEPT)).isEqualTo(MediaTypes.JSON);
- }
-
- @Test
- public void url_should_not_be_null() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Server URL must be set");
-
- new WsClient(newHttpConnector().build());
- }
-
- @Test
- public void url_should_not_be_empty() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Server URL must be set");
-
- new WsClient(newDefaultHttpConnector(""));
- }
-
- @Test
- public void test_default_configuration() throws Exception {
- underTest = new WsClient(newDefaultHttpConnector("http://localhost:9000"));
-
- HttpRequestFactory requestFactory = ((HttpConnector) underTest.wsConnector).requestFactory;
- assertThat(requestFactory.getBaseUrl()).isEqualTo("http://localhost:9000");
- assertThat(requestFactory.getLogin()).isNull();
- assertThat(requestFactory.getPassword()).isNull();
- assertThat(requestFactory.getConnectTimeoutInMilliseconds()).isEqualTo(HttpConnector.DEFAULT_CONNECT_TIMEOUT_MILLISECONDS);
- assertThat(requestFactory.getReadTimeoutInMilliseconds()).isEqualTo(HttpConnector.DEFAULT_READ_TIMEOUT_MILLISECONDS);
- assertThat(requestFactory.getProxyHost()).isNull();
- assertThat(requestFactory.getProxyPort()).isEqualTo(0);
- assertThat(requestFactory.getProxyLogin()).isNull();
- assertThat(requestFactory.getProxyPassword()).isNull();
- }
-
- @Test
- public void test_custom_configuration() throws Exception {
- underTest = new WsClient(newHttpConnector()
- .url("http://localhost:9000")
- .login("eric")
- .password("pass")
- .connectTimeoutMilliseconds(12345)
- .readTimeoutMilliseconds(6789)
- .proxy("localhost", 2052)
- .proxyLogin("proxyLogin")
- .proxyPassword("proxyPass")
- .build());
-
- HttpRequestFactory requestFactory = ((HttpConnector) underTest.wsConnector).requestFactory;
- assertThat(requestFactory.getBaseUrl()).isEqualTo("http://localhost:9000");
- assertThat(requestFactory.getLogin()).isEqualTo("eric");
- assertThat(requestFactory.getPassword()).isEqualTo("pass");
- assertThat(requestFactory.getConnectTimeoutInMilliseconds()).isEqualTo(12345);
- assertThat(requestFactory.getReadTimeoutInMilliseconds()).isEqualTo(6789);
- assertThat(requestFactory.getProxyHost()).isEqualTo("localhost");
- assertThat(requestFactory.getProxyPort()).isEqualTo(2052);
- assertThat(requestFactory.getProxyLogin()).isEqualTo("proxyLogin");
- assertThat(requestFactory.getProxyPassword()).isEqualTo("proxyPass");
- }
-}
+++ /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;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonarqube.ws.client.WsRequest.Method;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonarqube.ws.client.WsRequest.newGetRequest;
-import static org.sonarqube.ws.client.WsRequest.newPostRequest;
-
-public class WsRequestTest {
-
- static final String ENDPOINT = "api/issues/search";
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- WsRequest underTest;
-
- @Test
- public void get_request() {
- underTest = newGetRequest("api/issues/search");
-
- assertThat(underTest.getMethod()).isEqualTo(Method.GET);
- }
-
- @Test
- public void post_request() {
- underTest = newPostRequest("api/issues/search");
-
- assertThat(underTest.getMethod()).isEqualTo(Method.POST);
- }
-
- @Test
- public void set_non_null_param() {
- underTest = newGetRequest("api/issues/search")
- .setParam("key", "value");
-
- assertThat(underTest.getParams().get("key")).isEqualTo("value");
- }
-
- @Test
- public void set_null_param_remove_existing_param() {
- underTest = newGetRequest(ENDPOINT)
- .setParam("key", "value")
- .setParam("key", null);
-
- assertThat(underTest.getParams().get("key")).isNull();
- }
-
- @Test
- public void fail_if_key_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("a WS parameter key cannot be null");
-
- underTest = newGetRequest(ENDPOINT)
- .setParam(null, "value");
- }
-}
--- /dev/null
+// SonarQube, open source software quality management tool.
+// Copyright (C) 2008-2015 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.
+
+syntax = "proto2";
+
+package sonarqube.ws.testing;
+
+option java_package = "org.sonarqube.ws";
+option java_outer_classname = "Testing";
+option optimize_for = SPEED;
+
+message Fake {
+ optional string label = 1;
+}