import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
+import java.util.List;
import org.sonar.api.server.ws.LocalConnector;
import org.sonar.api.server.ws.internal.ValidatingRequest;
return localRequest.getParam(key);
}
+ @Override
+ protected List<String> readMultiParam(String key) {
+ throw new UnsupportedOperationException("reading multi value param is not supported yet by local WS calls");
+ }
+
@Override
protected InputStream readInputStreamParam(String key) {
String value = readParam(key);
*/
package org.sonar.server.ws;
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static java.util.Locale.ENGLISH;
-import static org.apache.commons.lang.StringUtils.substringAfterLast;
-import static org.apache.tomcat.util.http.fileupload.FileUploadBase.MULTIPART;
-
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.net.HttpHeaders;
import java.io.InputStream;
+import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
import javax.servlet.http.HttpServletRequest;
import org.sonar.api.server.ws.internal.ValidatingRequest;
import org.sonarqube.ws.MediaTypes;
+import static com.google.common.base.MoreObjects.firstNonNull;
+import static java.util.Collections.emptyList;
+import static java.util.Locale.ENGLISH;
+import static org.apache.commons.lang.StringUtils.substringAfterLast;
+import static org.apache.tomcat.util.http.fileupload.FileUploadBase.MULTIPART;
+
public class ServletRequest extends ValidatingRequest {
private final HttpServletRequest source;
return source.getParameter(key);
}
+ @Override
+ protected List<String> readMultiParam(String key) {
+ String[] values = source.getParameterValues(key);
+ return values == null ? emptyList() : ImmutableList.copyOf(values);
+ }
+
@Override
protected InputStream readInputStreamParam(String key) {
Part part = readPart(key);
*/
package org.sonar.server.ws;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import com.google.common.collect.ImmutableMap;
import com.google.common.net.HttpHeaders;
import java.io.InputStream;
+import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
import org.sonarqube.ws.MediaTypes;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
public class ServletRequestTest {
@Rule
HttpServletRequest source = mock(HttpServletRequest.class);
+ ServletRequest underTest = new ServletRequest(source);
+
@Test
public void call_method() {
- ServletRequest request = new ServletRequest(source);
- request.method();
+ underTest.method();
+
verify(source).getMethod();
}
public void getMediaType() throws Exception {
when(source.getHeader(HttpHeaders.ACCEPT)).thenReturn(MediaTypes.JSON);
when(source.getRequestURI()).thenReturn("/path/to/resource/search");
- ServletRequest request = new ServletRequest(source);
- assertThat(request.getMediaType()).isEqualTo(MediaTypes.JSON);
+
+ assertThat(underTest.getMediaType()).isEqualTo(MediaTypes.JSON);
}
@Test
public void default_media_type_is_octet_stream() throws Exception {
- ServletRequest request = new ServletRequest(source);
when(source.getRequestURI()).thenReturn("/path/to/resource/search");
- assertThat(request.getMediaType()).isEqualTo(MediaTypes.DEFAULT);
+
+ assertThat(underTest.getMediaType()).isEqualTo(MediaTypes.DEFAULT);
}
@Test
public void media_type_taken_in_url_first() throws Exception {
- ServletRequest request = new ServletRequest(source);
when(source.getHeader(HttpHeaders.ACCEPT)).thenReturn(MediaTypes.JSON);
when(source.getRequestURI()).thenReturn("/path/to/resource/search.protobuf");
- assertThat(request.getMediaType()).isEqualTo(MediaTypes.PROTOBUF);
+
+ assertThat(underTest.getMediaType()).isEqualTo(MediaTypes.PROTOBUF);
}
@Test
@Test
public void read_param_from_source() {
when(source.getParameter("param")).thenReturn("value");
- ServletRequest request = new ServletRequest(source);
- assertThat(request.readParam("param")).isEqualTo("value");
+
+ assertThat(underTest.readParam("param")).isEqualTo("value");
+ }
+
+ @Test
+ public void read_multi_param_from_source_with_values() {
+ when(source.getParameterValues("param")).thenReturn(new String[]{"firstValue", "secondValue", "thirdValue"});
+
+ List<String> result = underTest.readMultiParam("param");
+
+ assertThat(result).containsExactly("firstValue", "secondValue", "thirdValue");
+ }
+
+ @Test
+ public void read_multi_param_from_source_with_one_value() {
+ when(source.getParameterValues("param")).thenReturn(new String[]{"firstValue"});
+
+ List<String> result = underTest.readMultiParam("param");
+
+ assertThat(result).containsExactly("firstValue");
+ }
+
+ @Test
+ public void read_multi_param_from_source_without_value() {
+ when(source.getParameterValues("param")).thenReturn(null);
+
+ List<String> result = underTest.readMultiParam("param");
+
+ assertThat(result).isEmpty();
}
@Test
when(part.getSize()).thenReturn(10L);
when(source.getPart("param1")).thenReturn(part);
- ServletRequest request = new ServletRequest(source);
- assertThat(request.readInputStreamParam("param1")).isEqualTo(file);
-
- assertThat(request.readInputStreamParam("param2")).isNull();
+ assertThat(underTest.readInputStreamParam("param1")).isEqualTo(file);
+ assertThat(underTest.readInputStreamParam("param2")).isNull();
}
@Test
when(part.getSize()).thenReturn(0L);
when(source.getPart("param1")).thenReturn(part);
- ServletRequest request = new ServletRequest(source);
- assertThat(request.readInputStreamParam("param1")).isNull();
+ assertThat(underTest.readInputStreamParam("param1")).isNull();
}
@Test
public void return_no_input_stream_when_content_type_is_not_multipart() throws Exception {
when(source.getContentType()).thenReturn("multipart/form-data");
- ServletRequest request = new ServletRequest(source);
- assertThat(request.readInputStreamParam("param1")).isNull();
+
+ assertThat(underTest.readInputStreamParam("param1")).isNull();
}
@Test
public void return_no_input_stream_when_content_type_is_null() throws Exception {
when(source.getContentType()).thenReturn(null);
- ServletRequest request = new ServletRequest(source);
- assertThat(request.readInputStreamParam("param1")).isNull();
+
+ assertThat(underTest.readInputStreamParam("param1")).isNull();
}
@Test
when(part.getSize()).thenReturn(0L);
when(part.getInputStream()).thenReturn(file);
doThrow(IllegalArgumentException.class).when(source).getPart("param1");
- ServletRequest request = new ServletRequest(source);
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("Can't read file part");
- request.readInputStreamParam("param1");
+
+ underTest.readInputStreamParam("param1");
}
@Test
when(source.getRequestURI()).thenReturn("/sonar/path/to/resource/search");
when(source.getContextPath()).thenReturn("/sonar");
- ServletRequest request = new ServletRequest(source);
-
- assertThat(request.getPath()).isEqualTo("/path/to/resource/search");
+ assertThat(underTest.getPath()).isEqualTo("/path/to/resource/search");
}
@Test
public void to_string() {
when(source.getRequestURL()).thenReturn(new StringBuffer("http:localhost:9000/api/issues"));
- ServletRequest request = new ServletRequest(source);
- assertThat(request.toString()).isEqualTo("http:localhost:9000/api/issues");
+ assertThat(underTest.toString()).isEqualTo("http:localhost:9000/api/issues");
when(source.getQueryString()).thenReturn("components=sonar");
- request = new ServletRequest(source);
- assertThat(request.toString()).isEqualTo("http:localhost:9000/api/issues?components=sonar");
+
+ assertThat(underTest.toString()).isEqualTo("http:localhost:9000/api/issues?components=sonar");
}
}
*/
package org.sonar.server.ws;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import java.io.InputStream;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.sonar.api.server.ws.internal.PartImpl;
import org.sonar.api.server.ws.internal.ValidatingRequest;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
public class TestRequest extends ValidatingRequest {
private final Map<String, String> params = new HashMap<>();
return params.get(key);
}
+ @Override
+ protected List<String> readMultiParam(String key) {
+ String value = params.get(key);
+ return value == null ? emptyList() : singletonList(value);
+ }
+
@Override
protected InputStream readInputStreamParam(String key) {
String value = readParam(key);
*/
package org.sonar.server.ws;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.ws.RequestVerifier.verifyRequest;
-
import com.google.common.collect.Maps;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.test.JsonAssert;
import org.sonarqube.ws.MediaTypes;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.ws.RequestVerifier.verifyRequest;
+
/**
* @since 4.2
*/
return params.get(key);
}
+ @Override
+ protected List<String> readMultiParam(String key) {
+ String value = params.get(key);
+ return value == null ? emptyList() : singletonList(value);
+ }
+
@Override
protected InputStream readInputStreamParam(String key) {
String param = readParam(key);
*/
package org.sonar.api.server.ws;
-import static com.google.common.base.Preconditions.checkArgument;
-
import com.google.common.annotations.Beta;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.SonarException;
+import static com.google.common.base.Preconditions.checkArgument;
+
/**
* @since 4.2
*/
return values;
}
+ public List<String> mandatoryMultiParam(String key) {
+ List<String> values = multiParam(key);
+ if (values.isEmpty()) {
+ throw new IllegalArgumentException(String.format("The '%s' parameter is missing", key));
+ }
+
+ return values;
+ }
+
@CheckForNull
public List<String> paramAsStrings(String key) {
String value = param(key);
@CheckForNull
public abstract String param(String key);
+ public abstract List<String> multiParam(String key);
+
@CheckForNull
public abstract InputStream paramAsInputStream(String key);
*/
package org.sonar.api.server.ws.internal;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import com.google.common.collect.Maps;
import java.io.InputStream;
+import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
import org.sonar.api.server.ws.LocalConnector;
import org.sonar.api.server.ws.Request;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
/**
* Fake implementation of {@link org.sonar.api.server.ws.Request} used
* for testing. Call the method {@link #setParam(String, String)} to
return params.get(key);
}
+ @Override
+ public List<String> multiParam(String key) {
+ String value = params.get(key);
+ return value == null ? emptyList() : singletonList(value);
+ }
+
@Override
public InputStream paramAsInputStream(String key) {
return IOUtils.toInputStream(param(key));
*/
package org.sonar.api.server.ws.internal;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.log.Loggers;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
/**
* @since 4.2
*/
return param(key, true);
}
+ @Override
+ public List<String> multiParam(String key) {
+ WebService.Param definition = action.param(key);
+ List<String> values = readMultiParamOrDefaultValue(key, definition);
+
+ values.forEach(value -> validate(value, definition));
+
+ return values;
+ }
+
@Override
@CheckForNull
public InputStream paramAsInputStream(String key) {
return value;
}
+ private List<String> readMultiParamOrDefaultValue(String key, @Nullable WebService.Param definition) {
+ if (definition == null) {
+ String message = String.format("BUG - parameter '%s' is undefined for action '%s'", key, action.key());
+ Loggers.get(getClass()).error(message);
+ throw new IllegalArgumentException(message);
+ }
+
+ List<String> keyValues = readMultiParam(key);
+ if (!keyValues.isEmpty()) {
+ return keyValues;
+ }
+
+ String deprecatedKey = definition.deprecatedKey();
+ List<String> deprecatedKeyValues = deprecatedKey == null ? emptyList() : readMultiParam(deprecatedKey);
+ if (!deprecatedKeyValues.isEmpty()) {
+ return deprecatedKeyValues;
+ }
+
+ String defaultValue = definition.defaultValue();
+ return defaultValue == null ? emptyList() : singletonList(defaultValue);
+ }
+
@CheckForNull
protected abstract String readParam(String key);
+ protected abstract List<String> readMultiParam(String key);
+
@CheckForNull
protected abstract InputStream readInputStreamParam(String key);
*/
package org.sonar.api.server.ws;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-import com.google.common.collect.Maps;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
import org.sonar.api.server.ws.internal.ValidatingRequest;
import org.sonar.api.utils.DateUtils;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
public class RequestTest {
@Rule
underTest.mandatoryParamAsStrings("a_required_string");
}
+ @Test
+ public void mandatory_multi_param() {
+ underTest.setMultiParam("a_required_multi_param", newArrayList("firstValue", "secondValue", "thirdValue"));
+
+ List<String> result = underTest.mandatoryMultiParam("a_required_multi_param");
+
+ assertThat(result).containsExactly("firstValue", "secondValue", "thirdValue");
+ }
+
+ @Test
+ public void fail_when_no_multi_param() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("The 'a_required_multi_param' parameter is missing");
+
+ underTest.mandatoryMultiParam("a_required_multi_param");
+ }
+
@Test
public void default_value_of_optional_param() {
assertThat(underTest.param("has_default_string")).isEqualTo("the_default_string");
private static class FakeRequest extends ValidatingRequest {
- private final Map<String, String> params = Maps.newHashMap();
- private final Map<String, Part> parts = Maps.newHashMap();
+ private final ListMultimap<String, String> multiParams = ArrayListMultimap.create();
+ private final Map<String, String> params = new HashMap<>();
+ private final Map<String, Part> parts = new HashMap<>();
@Override
public String method() {
return this;
}
+ public FakeRequest setMultiParam(String key, List<String> values) {
+ multiParams.putAll(key, values);
+
+ return this;
+ }
+
@Override
protected String readParam(String key) {
return params.get(key);
}
+ @Override
+ protected List<String> readMultiParam(String key) {
+ return multiParams.get(key);
+ }
+
@Override
protected InputStream readInputStreamParam(String key) {
String param = readParam(key);
action.createParam("a_required_boolean").setRequired(true);
action.createParam("a_required_number").setRequired(true);
action.createParam("a_required_enum").setRequired(true);
+ action.createParam("a_required_multi_param").setRequired(true);
action.createParam("has_default_string").setDefaultValue("the_default_string");
action.createParam("has_default_number").setDefaultValue("10");