checkRequest(activityWsRequest.getComponentId() == null || activityWsRequest.getQuery() == null, "%s and %s must not be set at the same time",
PARAM_COMPONENT_ID, PARAM_COMPONENT_QUERY);
- checkRequest(activityWsRequest.getPageSize() <= MAX_PAGE_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_PAGE_SIZE);
-
return activityWsRequest;
}
}
.setAsc(request.mandatoryParamAsBoolean(Param.ASCENDING))
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE));
- checkRequest(treeWsRequest.getPageSize() <= MAX_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_SIZE);
String searchQuery = treeWsRequest.getQuery();
checkRequest(searchQuery == null || searchQuery.length() >= QUERY_MINIMUM_LENGTH,
"The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, QUERY_MINIMUM_LENGTH);
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
.setQuery(request.param(Param.TEXT_QUERY));
- checkRequest(componentTreeWsRequest.getPageSize() <= MAX_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_SIZE);
String searchQuery = componentTreeWsRequest.getQuery();
checkRequest(searchQuery == null || searchQuery.length() >= QUERY_MINIMUM_LENGTH,
"The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, QUERY_MINIMUM_LENGTH);
private static SearchOptions buildSearchOptions(Request request) {
int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE);
- checkArgument(pageSize <= SearchOptions.MAX_LIMIT, "Page size must lower than or equal to %s", SearchOptions.MAX_LIMIT);
-
return new SearchOptions().setPage(request.mandatoryParamAsInt(Param.PAGE), pageSize);
}
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UserSession;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Comparator.comparing;
import static org.sonar.api.utils.Paging.forPageIndex;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
String query = request.param(Param.TEXT_QUERY);
int page = request.mandatoryParamAsInt(Param.PAGE);
int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE);
- checkArgument(pageSize <= MAX_PAGE_SIZE, "The '%s' parameter must be less than %s", Param.PAGE_SIZE, MAX_PAGE_SIZE);
List<ProjectQprofileAssociationDto> projects = loadAllProjects(profileKey, session, selected, query).stream()
.sorted(comparing(ProjectQprofileAssociationDto::getProjectName)
import com.google.common.collect.Ordering;
import java.util.Comparator;
import java.util.List;
-import java.util.Set;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.core.util.stream.MoreCollectors;
import static com.google.common.base.Preconditions.checkState;
+import static java.util.Optional.ofNullable;
public class ListAction implements WebServicesWsAction {
private WebService.Context context;
writer.prop("deprecatedKey", param.deprecatedKey());
writer.prop("deprecatedKeySince", param.deprecatedKeySince());
writer.prop("maxValuesAllowed", param.maxValuesAllowed());
- Set<String> possibleValues = param.possibleValues();
- if (possibleValues != null) {
- writer.name("possibleValues").beginArray().values(possibleValues).endArray();
- }
- Integer maximumLength = param.maximumLength();
- if (maximumLength != null) {
- writer.prop("maximumLength", maximumLength);
- }
+ ofNullable(param.possibleValues()).ifPresent(possibleValues -> writer.name("possibleValues").beginArray().values(possibleValues).endArray());
+ ofNullable(param.maximumLength()).ifPresent(maximumLength -> writer.prop("maximumLength", maximumLength));
+ ofNullable(param.maximumValue()).ifPresent(maximumValue -> writer.prop("maximumValue", maximumValue));
writer.endObject();
}
}
],
"params": [
+ {
+ "key": "maximum_value",
+ "maximumValue": 12,
+ "required": false,
+ "internal": false
+ },
{
"key": "name",
"required": false,
@Test
public void fail_if_page_size_greater_than_1000() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("The 'ps' parameter must be less than 1000");
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("'ps' value (1001) must be less than 1000");
ws.newRequest()
.setParam(Param.PAGE_SIZE, "1001")
@Test
public void fail_when_page_size_above_500() {
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("The 'ps' parameter must be less than 500");
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("'ps' value (501) must be less than 500");
componentDb.insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid"));
db.commit();
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.db.component.ComponentTesting.newProjectCopy;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
db.components().insertSnapshot(project);
insertNclocMetric();
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("The 'ps' parameter must be less than 500");
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("'ps' value (2540) must be less than 500");
ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
.setParam(PARAM_METRIC_KEYS, "ncloc")
.setParam(Param.PAGE_SIZE, "2540")
- .executeProtobuf(ComponentTreeWsResponse.class);
+ .execute();
}
@Test
request.setPageSize(501);
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Page size must lower than or equal to 500");
+ expectedException.expectMessage("'ps' value (501) must be less than 500");
call();
}
@Test
public void fail_if_page_size_greater_than_500() throws Exception {
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("The 'ps' parameter must be less than 500");
+ expectedException.expectMessage("'ps' value (501) must be less than 500");
newRequest().setParam(PARAM_KEY, xooP1.getKee()).setParam(Param.PAGE_SIZE, "501").execute();
}
.setDefaultValue("BLOCKER");
create.createParam("name");
create.createParam("internal").setInternal(true);
+ create.createParam("maximum_value").setMaximumValue(12);
newController.createAction("internal_action")
.setDescription("Internal Action Description")
-{"webServices": [
- {
- "path": "api/metric",
- "since": "3.2",
- "description": "Metrics",
- "actions": [
- {
- "key": "create",
- "description": "Create metric",
- "since": "4.1",
- "internal": false,
- "post": true,
- "hasResponseExample": true,
- "params": [
- {
- "key": "name",
- "required": false,
- "internal": false
- },
- {
- "key": "severity",
- "description": "Severity",
- "required": false,
- "internal": false,
- "defaultValue": "BLOCKER",
- "exampleValue": "INFO",
- "possibleValues": ["BLOCKER", "INFO"]
- },
- {
- "key": "internal",
- "required": false,
- "internal": true
- }
- ]
- },
- {
- "key": "internal_action",
- "since": "5.3",
- "internal": true,
- "post": false,
- "hasResponseExample": true
- },
- {
- "key": "show",
- "since": "3.2",
- "internal": false,
- "post": false,
- "hasResponseExample": true
- }
- ]
- },
- {
- "path": "api/webservices",
- "description": "Get information on the web api supported on this instance.",
- "since": "4.2",
- "actions": [
- {
- "key": "list",
- "since": "4.2",
- "description": "List web services",
- "internal": false,
- "post": false,
- "hasResponseExample": true,
- "params": [
- {
- "key": "include_internals",
- "description": "Include web services that are implemented for internal use only. Their forward-compatibility is not assured",
- "required": false,
- "internal": false,
- "defaultValue": "false",
- "possibleValues": ["true", "false", "yes", "no"]
- }
- ]
- },
- {
- "key": "response_example",
- "since": "4.4",
- "description": "Display web service response example",
- "internal": false,
- "post": false,
- "hasResponseExample": true,
- "params": [
- {
- "key": "action",
- "required": true,
- "internal": false,
- "description": "Action of the web service",
- "exampleValue": "search"
- },
- {
- "key": "controller",
- "required": true,
- "internal": false,
- "description": "Controller of the web service",
- "exampleValue": "api/issues"
- }
- ]
- }
- ]
- }
-]}
+{
+ "webServices": [
+ {
+ "path": "api/metric",
+ "since": "3.2",
+ "description": "Metrics",
+ "actions": [
+ {
+ "key": "create",
+ "description": "Create metric",
+ "since": "4.1",
+ "internal": false,
+ "post": true,
+ "hasResponseExample": true,
+ "params": [
+ {
+ "key": "maximum_value",
+ "maximumValue": 12
+ },
+ {
+ "key": "name",
+ "required": false,
+ "internal": false
+ },
+ {
+ "key": "severity",
+ "description": "Severity",
+ "required": false,
+ "internal": false,
+ "defaultValue": "BLOCKER",
+ "exampleValue": "INFO",
+ "possibleValues": [
+ "BLOCKER",
+ "INFO"
+ ]
+ },
+ {
+ "key": "internal",
+ "required": false,
+ "internal": true
+ }
+ ]
+ },
+ {
+ "key": "internal_action",
+ "since": "5.3",
+ "internal": true,
+ "post": false,
+ "hasResponseExample": true
+ },
+ {
+ "key": "show",
+ "since": "3.2",
+ "internal": false,
+ "post": false,
+ "hasResponseExample": true
+ }
+ ]
+ },
+ {
+ "path": "api/webservices",
+ "description": "Get information on the web api supported on this instance.",
+ "since": "4.2",
+ "actions": [
+ {
+ "key": "list",
+ "since": "4.2",
+ "description": "List web services",
+ "internal": false,
+ "post": false,
+ "hasResponseExample": true,
+ "params": [
+ {
+ "key": "include_internals",
+ "description": "Include web services that are implemented for internal use only. Their forward-compatibility is not assured",
+ "required": false,
+ "internal": false,
+ "defaultValue": "false",
+ "possibleValues": [
+ "true",
+ "false",
+ "yes",
+ "no"
+ ]
+ }
+ ]
+ },
+ {
+ "key": "response_example",
+ "since": "4.4",
+ "description": "Display web service response example",
+ "internal": false,
+ "post": false,
+ "hasResponseExample": true,
+ "params": [
+ {
+ "key": "action",
+ "required": true,
+ "internal": false,
+ "description": "Action of the web service",
+ "exampleValue": "search"
+ },
+ {
+ "key": "controller",
+ "required": true,
+ "internal": false,
+ "description": "Controller of the web service",
+ "exampleValue": "api/issues"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
public NewParam createPageSize(int defaultPageSize, int maxPageSize) {
return createParam(Param.PAGE_SIZE)
- .setDescription("Page size. Must be greater than 0 and less than " + maxPageSize)
- .setExampleValue("20")
.setDeprecatedKey("pageSize", "5.2")
- .setDefaultValue(String.valueOf(defaultPageSize));
+ .setDefaultValue(String.valueOf(defaultPageSize))
+ .setMaximumValue(maxPageSize)
+ .setDescription("Page size. Must be greater than 0 and less than " + maxPageSize)
+ .setExampleValue("20");
}
/**
private Set<String> possibleValues = null;
private Integer maxValuesAllowed;
private Integer maximumLength;
+ private Integer maximumValue;
private NewParam(String key) {
this.key = key;
return this;
}
+ /**
+ * @since 7.0
+ */
+ public NewParam setMaximumValue(@Nullable Integer maximumValue) {
+ this.maximumValue = maximumValue;
+ return this;
+ }
+
@Override
public String toString() {
return key;
private final boolean internal;
private final Set<String> possibleValues;
private final Integer maximumLength;
+ private final Integer maximumValue;
private final Integer maxValuesAllowed;
protected Param(Action action, NewParam newParam) {
this.possibleValues = newParam.possibleValues;
this.maxValuesAllowed = newParam.maxValuesAllowed;
this.maximumLength = newParam.maximumLength;
+ this.maximumValue = newParam.maximumValue;
checkArgument(!required || defaultValue == null, "Default value must not be set on parameter '%s?%s' as it's marked as required", action, key);
}
}
/**
- * Specify the maximum number of values allowed when using this a parameter
+ * Specify the maximum number of values allowed when using {@link Request#multiParam(String)}
*
* @since 6.4
*/
return maximumLength;
}
+ /**
+ * Specify the maximum value of the numeric variable used in this parameter
+ *
+ * @since 7.0
+ */
+ @CheckForNull
+ public Integer maximumValue() {
+ return maximumValue;
+ }
+
@Override
public String toString() {
return key;
import org.sonar.api.server.ws.WebService;
import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Objects.requireNonNull;
@CheckForNull
public String param(String key) {
WebService.Param definition = action.param(key);
- String value = defaultString(readParam(key, definition), definition.defaultValue());
-
- Integer maximumLength = definition.maximumLength();
- if (value != null && maximumLength != null) {
- int valueLength = value.length();
- checkArgument(valueLength <= maximumLength,
- "'%s' length (%s) is longer than the maximum authorized (%s)",
- key, valueLength, maximumLength);
- }
-
- String trimmedValue = value == null ? null : CharMatcher.WHITESPACE.trimFrom(value);
- if (trimmedValue != null) {
- validateValue(trimmedValue, definition);
+ String valueOrDefault = defaultString(readParam(key, definition), definition.defaultValue());
+ String value = valueOrDefault == null ? null : CharMatcher.WHITESPACE.trimFrom(valueOrDefault);
+ if (value == null) {
+ return null;
}
- return trimmedValue;
+ validatePossibleValues(key, value, definition);
+ validateMaximumLength(key, definition, valueOrDefault);
+ validateMaximumValue(key, definition, value);
+ return value;
}
@Override
private static List<String> validateValues(List<String> values, WebService.Param definition) {
Integer maximumValues = definition.maxValuesAllowed();
checkArgument(maximumValues == null || values.size() <= maximumValues, "'%s' can contains only %s values, got %s", definition.key(), maximumValues, values.size());
- values.forEach(value -> validateValue(value, definition));
+ values.forEach(value -> validatePossibleValues(definition.key(), value, definition));
return values;
}
- private static void validateValue(String value, WebService.Param definition) {
+ private static void validatePossibleValues(String key, String value, WebService.Param definition) {
Set<String> possibleValues = definition.possibleValues();
- checkArgument(possibleValues == null || possibleValues.contains(value), "Value of parameter '%s' (%s) must be one of: %s", definition.key(), value, possibleValues);
+ if (possibleValues == null) {
+ return;
+ }
+ checkArgument(possibleValues.contains(value), "Value of parameter '%s' (%s) must be one of: %s", key, value, possibleValues);
}
+
+ private static void validateMaximumLength(String key, WebService.Param definition, String valueOrDefault) {
+ Integer maximumLength = definition.maximumLength();
+ if (maximumLength == null) {
+ return;
+ }
+ int valueLength = valueOrDefault.length();
+ checkArgument(valueLength <= maximumLength, "'%s' length (%s) is longer than the maximum authorized (%s)", key, valueLength, maximumLength);
+ }
+
+ private static void validateMaximumValue(String key, WebService.Param definition, String value) {
+ Integer maximumValue = definition.maximumValue();
+ if (maximumValue == null) {
+ return;
+ }
+ int valueAsInt = validateAsNumeric(key, value);
+ checkArgument(valueAsInt <= maximumValue, "'%s' value (%s) must be less than %s", key, valueAsInt, maximumValue);
+ }
+
+ private static int validateAsNumeric(String key, String value) {
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException exception) {
+ throw new IllegalStateException(format("'%s' value '%s' cannot be parsed as an integer", key, value), exception);
+ }
+ }
+
}
underTest.setParam(parameter, repeat("X", 11)).param(parameter);
}
+ @Test
+ public void maximum_value_ok() {
+ String param = "maximum_value_param";
+ defineParameterTestAction(newParam -> newParam.setMaximumValue(10), param);
+ String expected = "10";
+
+ String actual = underTest.setParam(param, expected).param(param);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Test
+ public void maximum_value_not_ok() {
+ String param = "maximum_value_param";
+ defineParameterTestAction(newParam -> newParam.setMaximumValue(10), param);
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage(format("'%s' value (11) must be less than 10", param));
+
+ underTest.setParam(param, "11").param(param);
+ }
+
@Test
public void required_param_as_strings() {
underTest.setParam("a_required_string", "foo,bar");
@DataProvider
public static Object[][] date_times() {
- return new Object[][]{
+ return new Object[][] {
{"2014-05-27", parseDate("2014-05-27")},
{"2014-05-27T15:50:45+0100", parseDateTime("2014-05-27T15:50:45+0100")},
{null, null}
assertThat(action.param("string_value").maximumLength()).isEqualTo(24);
}
+ @Test
+ public void param_with_maximum_value() {
+ ((WebService) context -> {
+ NewController newController = context.createController("api/custom_measures");
+ NewAction create = newDefaultAction(newController, "create");
+ create.createParam("numeric_value")
+ .setMaximumValue(10);
+ newController.done();
+ }).define(context);
+
+ WebService.Action action = context.controller("api/custom_measures").action("create");
+ assertThat(action.param("numeric_value").maximumValue()).isEqualTo(10);
+ }
+
@Test
public void fail_if_required_param_has_default_value() {
expectedException.expect(IllegalArgumentException.class);