Skip to content

Commit

Permalink
SONAR-7969 Create client for values WS
Browse files Browse the repository at this point in the history
  • Loading branch information
julienlancelot committed Aug 25, 2016
1 parent 4beb2af commit 7d3c462
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 20 deletions.
Expand Up @@ -34,41 +34,49 @@
import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.util.stream.Collectors; import org.sonar.core.util.stream.Collectors;
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Settings; import org.sonarqube.ws.Settings;
import org.sonarqube.ws.Settings.ValuesWsResponse; import org.sonarqube.ws.Settings.ValuesWsResponse;
import org.sonarqube.ws.client.setting.ValuesRequest;


import static org.elasticsearch.common.Strings.isNullOrEmpty; import static org.elasticsearch.common.Strings.isNullOrEmpty;
import static org.sonar.api.PropertyType.PROPERTY_SET; import static org.sonar.api.PropertyType.PROPERTY_SET;
import static org.sonar.server.component.ComponentFinder.ParamNames.ID_AND_KEY;
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.addComponentParameters; import static org.sonar.server.settings.ws.SettingsWsComponentParameters.addComponentParameters;
import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_VALUES;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_ID; import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_ID;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_KEY; import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_KEY;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;


public class ValuesAction implements SettingsWsAction { public class ValuesAction implements SettingsWsAction {


private static final Splitter COMMA_SPLITTER = Splitter.on(","); private static final Splitter COMMA_SPLITTER = Splitter.on(",");


private static final String PARAM_KEYS = "keys";

private final DbClient dbClient; private final DbClient dbClient;
private final SettingsWsComponentParameters settingsWsComponentParameters; private final ComponentFinder componentFinder;
private final UserSession userSession;
private final PropertyDefinitions propertyDefinitions; private final PropertyDefinitions propertyDefinitions;
private final SettingsFinder settingsFinder; private final SettingsFinder settingsFinder;


public ValuesAction(DbClient dbClient, SettingsWsComponentParameters settingsWsComponentParameters, PropertyDefinitions propertyDefinitions, SettingsFinder settingsFinder) { public ValuesAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, PropertyDefinitions propertyDefinitions, SettingsFinder settingsFinder) {
this.dbClient = dbClient; this.dbClient = dbClient;
this.settingsWsComponentParameters = settingsWsComponentParameters; this.componentFinder = componentFinder;
this.userSession = userSession;
this.propertyDefinitions = propertyDefinitions; this.propertyDefinitions = propertyDefinitions;
this.settingsFinder = settingsFinder; this.settingsFinder = settingsFinder;
} }


@Override @Override
public void define(WebService.NewController context) { public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("values") WebService.NewAction action = context.createAction(ACTION_VALUES)
.setDescription("List settings values.<br>" + .setDescription("List settings values.<br>" +
"If no value has been set for a setting, then the default value is returned.<br>" + "If no value has been set for a setting, then the default value is returned.<br>" +
"Either '%s' or '%s' can be provided, not both.<br> " + "Either '%s' or '%s' can be provided, not both.<br> " +
Expand All @@ -82,7 +90,7 @@ public void define(WebService.NewController context) {
.setHandler(this); .setHandler(this);
addComponentParameters(action); addComponentParameters(action);
action.createParam(PARAM_KEYS) action.createParam(PARAM_KEYS)
.setDescription("List of property keys") .setDescription("List of setting keys")
.setRequired(true) .setRequired(true)
.setExampleValue("sonar.technicalDebt.hoursInDay,sonar.dbcleaner.cleanDirectory"); .setExampleValue("sonar.technicalDebt.hoursInDay,sonar.dbcleaner.cleanDirectory");
} }
Expand All @@ -95,16 +103,41 @@ public void handle(Request request, Response response) throws Exception {
private ValuesWsResponse doHandle(Request request) { private ValuesWsResponse doHandle(Request request) {
DbSession dbSession = dbClient.openSession(true); DbSession dbSession = dbClient.openSession(true);
try { try {
ComponentDto componentDto = settingsWsComponentParameters.getComponent(dbSession, request); ValuesRequest valuesRequest = toWsRequest(request);
settingsWsComponentParameters.checkAdminPermission(componentDto); Optional<ComponentDto> component = getComponent(dbSession, valuesRequest);
Set<String> keys = new HashSet<>(request.mandatoryParamAsStrings(PARAM_KEYS)); checkAdminPermission(component);
Optional<ComponentDto> component = Optional.ofNullable(componentDto); Set<String> keys = new HashSet<>(valuesRequest.getKeys());
return new ValuesResponseBuilder(loadSettings(dbSession, component, keys), component).build(); return new ValuesResponseBuilder(loadSettings(dbSession, component, keys), component).build();
} finally { } finally {
dbClient.closeSession(dbSession); dbClient.closeSession(dbSession);
} }
} }


private static ValuesRequest toWsRequest(Request request) {
return ValuesRequest.builder()
.setKeys(request.mandatoryParamAsStrings(PARAM_KEYS))
.setComponentId(request.param(PARAM_COMPONENT_ID))
.setComponentKey(request.param(PARAM_COMPONENT_KEY))
.build();
}

private Optional<ComponentDto> getComponent(DbSession dbSession, ValuesRequest valuesRequest) {
String componentId = valuesRequest.getComponentId();
String componentKey = valuesRequest.getComponentKey();
if (componentId != null || componentKey != null) {
return Optional.of(componentFinder.getByUuidOrKey(dbSession, componentId, componentKey, ID_AND_KEY));
}
return Optional.empty();
}

private void checkAdminPermission(Optional<ComponentDto> component) {
if (component.isPresent()) {
userSession.checkComponentUuidPermission(UserRole.ADMIN, component.get().uuid());
} else {
userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN);
}
}

private List<Setting> loadSettings(DbSession dbSession, Optional<ComponentDto> component, Set<String> keys) { private List<Setting> loadSettings(DbSession dbSession, Optional<ComponentDto> component, Set<String> keys) {
if (keys.isEmpty()) { if (keys.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
Expand Down
Expand Up @@ -78,13 +78,12 @@ public class ValuesActionTest {
DbClient dbClient = db.getDbClient(); DbClient dbClient = db.getDbClient();
DbSession dbSession = db.getSession(); DbSession dbSession = db.getSession();
ComponentDbTester componentDb = new ComponentDbTester(db); ComponentDbTester componentDb = new ComponentDbTester(db);
SettingsWsComponentParameters settingsWsComponentParameters = new SettingsWsComponentParameters(new ComponentFinder(dbClient), userSession);
PropertyDefinitions propertyDefinitions = new PropertyDefinitions(); PropertyDefinitions propertyDefinitions = new PropertyDefinitions();
SettingsFinder settingsFinder = new SettingsFinder(dbClient, propertyDefinitions); SettingsFinder settingsFinder = new SettingsFinder(dbClient, propertyDefinitions);


ComponentDto project; ComponentDto project;


WsActionTester ws = new WsActionTester(new ValuesAction(dbClient, settingsWsComponentParameters, propertyDefinitions, settingsFinder)); WsActionTester ws = new WsActionTester(new ValuesAction(dbClient, new ComponentFinder(dbClient), userSession, propertyDefinitions, settingsFinder));


@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
Expand Down Expand Up @@ -376,7 +375,7 @@ public void fail_when_not_system_admin() throws Exception {
propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build()); propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build());


expectedException.expect(ForbiddenException.class); expectedException.expect(ForbiddenException.class);
newRequestForGlobalProperties(); newRequestForGlobalProperties("foo");
} }


@Test @Test
Expand All @@ -385,7 +384,7 @@ public void fail_when_not_project_admin() throws Exception {
propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build()); propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build());


expectedException.expect(ForbiddenException.class); expectedException.expect(ForbiddenException.class);
newRequest(project.uuid(), null); newRequest(project.uuid(), null, "foo");
} }


@Test @Test
Expand Down
Expand Up @@ -20,14 +20,17 @@
package org.sonarqube.ws.client.setting; package org.sonarqube.ws.client.setting;


import org.sonarqube.ws.Settings.ListDefinitionsWsResponse; import org.sonarqube.ws.Settings.ListDefinitionsWsResponse;
import org.sonarqube.ws.Settings.ValuesWsResponse;
import org.sonarqube.ws.client.BaseService; import org.sonarqube.ws.client.BaseService;
import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsConnector; import org.sonarqube.ws.client.WsConnector;


import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_ID; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_ID;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEY; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEY;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_LIST_DEFINITIONS; import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_LIST_DEFINITIONS;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_VALUES;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.CONTROLLER_SETTINGS; import static org.sonarqube.ws.client.setting.SettingsWsParameters.CONTROLLER_SETTINGS;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;


public class SettingsService extends BaseService { public class SettingsService extends BaseService {
public SettingsService(WsConnector wsConnector) { public SettingsService(WsConnector wsConnector) {
Expand All @@ -41,4 +44,12 @@ public ListDefinitionsWsResponse listDefinitions(ListDefinitionsRequest request)
return call(getRequest, ListDefinitionsWsResponse.parser()); return call(getRequest, ListDefinitionsWsResponse.parser());
} }


public ValuesWsResponse values(ValuesRequest request) {
GetRequest getRequest = new GetRequest(path(ACTION_VALUES))
.setParam(PARAM_KEYS, inlineMultipleParamValue(request.getKeys()))
.setParam(PARAM_COMPONENT_ID, request.getComponentId())
.setParam(PARAM_COMPONENT_KEY, request.getComponentKey());
return call(getRequest, ValuesWsResponse.parser());
}

} }
Expand Up @@ -24,8 +24,14 @@ public class SettingsWsParameters {
public static final String CONTROLLER_SETTINGS = "api/settings"; public static final String CONTROLLER_SETTINGS = "api/settings";


public static final String ACTION_LIST_DEFINITIONS = "list_definitions"; public static final String ACTION_LIST_DEFINITIONS = "list_definitions";
public static final String ACTION_VALUES = "values";


public static final String PARAM_COMPONENT_ID = "componentId"; public static final String PARAM_COMPONENT_ID = "componentId";
public static final String PARAM_COMPONENT_KEY = "componentKey"; public static final String PARAM_COMPONENT_KEY = "componentKey";
public static final String PARAM_KEYS = "keys";

private SettingsWsParameters() {
// Only static stuff
}


} }
@@ -0,0 +1,97 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonarqube.ws.client.setting;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Arrays.asList;
import static java.util.Objects.requireNonNull;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;

public class ValuesRequest {

private final String componentId;
private final String componentKey;
private final List<String> keys;

public ValuesRequest(Builder builder) {
this.componentId = builder.componentId;
this.componentKey = builder.componentKey;
this.keys = builder.keys;
}

@CheckForNull
public String getComponentId() {
return componentId;
}

@CheckForNull
public String getComponentKey() {
return componentKey;
}

public List<String> getKeys() {
return keys;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private String componentId;
private String componentKey;
private List<String> keys = new ArrayList<>();

private Builder() {
// enforce factory method use
}

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

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

public Builder setKeys(List<String> keys) {
this.keys = requireNonNull(keys);
return this;
}

public Builder setKeys(String... keys) {
return setKeys(asList(keys));
}

public ValuesRequest build() {
checkArgument(!keys.isEmpty(), "'%s' cannot be empty", PARAM_KEYS);
return new ValuesRequest(this);
}
}

}
Expand Up @@ -22,14 +22,16 @@


import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.sonarqube.ws.Settings; import org.sonarqube.ws.Settings.ListDefinitionsWsResponse;
import org.sonarqube.ws.Settings.ValuesWsResponse;
import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.ServiceTester; import org.sonarqube.ws.client.ServiceTester;
import org.sonarqube.ws.client.WsConnector; import org.sonarqube.ws.client.WsConnector;


import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_KEY; import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_KEY;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;


public class SettingsServiceTest { public class SettingsServiceTest {


Expand All @@ -40,15 +42,28 @@ public class SettingsServiceTest {


@Test @Test
public void list_definitions() { public void list_definitions() {
ListDefinitionsRequest request = ListDefinitionsRequest.builder() underTest.listDefinitions(ListDefinitionsRequest.builder()
.setComponentKey("KEY") .setComponentKey("KEY")
.build(); .build());
GetRequest getRequest = serviceTester.getGetRequest();

assertThat(serviceTester.getGetParser()).isSameAs(ListDefinitionsWsResponse.parser());
serviceTester.assertThat(getRequest)
.hasParam(PARAM_COMPONENT_KEY, "KEY")
.andNoOtherParam();
}


underTest.listDefinitions(request); @Test
public void values() {
underTest.values(ValuesRequest.builder()
.setKeys("sonar.debt,sonar.issue")
.setComponentKey("KEY")
.build());
GetRequest getRequest = serviceTester.getGetRequest(); GetRequest getRequest = serviceTester.getGetRequest();


assertThat(serviceTester.getGetParser()).isSameAs(Settings.ListDefinitionsWsResponse.parser()); assertThat(serviceTester.getGetParser()).isSameAs(ValuesWsResponse.parser());
serviceTester.assertThat(getRequest) serviceTester.assertThat(getRequest)
.hasParam(PARAM_KEYS, "sonar.debt,sonar.issue")
.hasParam(PARAM_COMPONENT_KEY, "KEY") .hasParam(PARAM_COMPONENT_KEY, "KEY")
.andNoOtherParam(); .andNoOtherParam();
} }
Expand Down

0 comments on commit 7d3c462

Please sign in to comment.