--- /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.server.util;
+
+public class ObjectUtils {
+
+ /**
+ * Taken from http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/src-html/org/apache/commons/lang3/ObjectUtils.html#line.119
+ * <p>Returns the first value in the array which is not {@code null}.
+ * If all the values are {@code null} or the array is {@code null}
+ * or empty then {@code null} is returned.</p>
+ *
+ * <pre>
+ * ObjectUtils.firstNonNull(null, null) = null
+ * ObjectUtils.firstNonNull(null, "") = ""
+ * ObjectUtils.firstNonNull(null, null, "") = ""
+ * ObjectUtils.firstNonNull(null, "zz") = "zz"
+ * ObjectUtils.firstNonNull("abc", *) = "abc"
+ * ObjectUtils.firstNonNull(null, "xyz", *) = "xyz"
+ * ObjectUtils.firstNonNull(Boolean.TRUE, *) = Boolean.TRUE
+ * ObjectUtils.firstNonNull() = null
+ * </pre>
+ *
+ * @param <T> the component type of the array
+ * @param values the values to test, may be {@code null} or empty
+ * @return the first value from {@code values} which is not {@code null},
+ * or {@code null} if there are no non-null values
+ * @since 3.0
+ */
+ public static <T> T firstNonNull(T... values) {
+ if (values != null) {
+ for (T val : values) {
+ if (val != null) {
+ return val;
+ }
+ }
+ }
+ return null;
+ }
+}
*/
package org.sonar.server.ws;
-import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+import java.io.InputStream;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.servlet.http.HttpServletRequest;
import org.jruby.RubyFile;
import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.server.plugins.MimeTypes;
-import javax.servlet.http.HttpServletRequest;
-
-import java.io.InputStream;
-import java.util.Map;
+import static org.sonar.server.util.ObjectUtils.firstNonNull;
public class ServletRequest extends ValidatingRequest {
private final HttpServletRequest source;
private final Map<String, Object> params;
+ private static final Map<String, String> SUPPORTED_FORMATS = ImmutableMap.of(
+ "JSON", MimeTypes.JSON,
+ "PROTOBUF", MimeTypes.PROTOBUF,
+ "TEXT", MimeTypes.TXT);
public ServletRequest(HttpServletRequest source, Map<String, Object> params) {
this.source = source;
@Override
public String getMediaType() {
- return Objects.firstNonNull(source.getContentType(), "application/octet-stream");
+ String mediaTypeFromUrl = mediaTypeFromUrl(source.getRequestURI());
+ return firstNonNull(mediaTypeFromUrl, source.getContentType(), MimeTypes.DEFAULT);
}
@Override
}
return url.toString();
}
+
+ @CheckForNull
+ private static String mediaTypeFromUrl(String url) {
+ String mediaType = url.substring(url.lastIndexOf('.') + 1);
+ return SUPPORTED_FORMATS.get(mediaType.toUpperCase());
+ }
}
*/
package org.sonar.server.ws;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
import org.picocontainer.Startable;
import org.sonar.api.i18n.I18n;
import org.sonar.api.server.ServerSide;
import org.sonar.server.plugins.MimeTypes;
import org.sonar.server.user.UserSession;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
+import static java.lang.String.format;
import static org.sonar.server.ws.RequestVerifier.verifyRequest;
/**
}
private WebService.Action getAction(String controllerPath, String actionKey) {
+ String actionKeyWithoutFormatSuffix = actionKey.contains(".") ?
+ actionKey.substring(0, actionKey.lastIndexOf('.'))
+ : actionKey;
WebService.Controller controller = context.controller(controllerPath);
if (controller == null) {
- throw new BadRequestException(String.format("Unknown web service: %s", controllerPath));
+ throw new BadRequestException(format("Unknown web service: %s", controllerPath));
}
- WebService.Action action = controller.action(actionKey);
+ WebService.Action action = controller.action(actionKeyWithoutFormatSuffix);
if (action == null) {
- throw new BadRequestException(String.format("Unknown action: %s/%s", controllerPath, actionKey));
+ throw new BadRequestException(format("Unknown action: %s/%s", controllerPath, actionKeyWithoutFormatSuffix));
}
return action;
}
package org.sonar.server.ws;
import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
+import javax.servlet.http.HttpServletRequest;
import org.jruby.RubyFile;
import org.junit.Test;
-
-import javax.servlet.http.HttpServletRequest;
-
-import java.util.Collections;
import org.sonar.server.plugins.MimeTypes;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class ServletRequestTest {
@Test
public void getMediaType() throws Exception {
when(source.getContentType()).thenReturn(MimeTypes.JSON);
+ when(source.getRequestURI()).thenReturn("/path/to/resource/search");
ServletRequest request = new ServletRequest(source, Collections.<String, Object>emptyMap());
assertThat(request.getMediaType()).isEqualTo(MimeTypes.JSON);
}
@Test
public void default_media_type_is_octet_stream() throws Exception {
ServletRequest request = new ServletRequest(source, Collections.<String, Object>emptyMap());
- assertThat(request.getMediaType()).isEqualTo("application/octet-stream");
+ when(source.getRequestURI()).thenReturn("/path/to/resource/search");
+ assertThat(request.getMediaType()).isEqualTo(MimeTypes.DEFAULT);
+ }
+
+ @Test
+ public void media_type_taken_in_url_first() throws Exception {
+ ServletRequest request = new ServletRequest(source, Collections.<String, Object>emptyMap());
+ when(source.getContentType()).thenReturn(MimeTypes.JSON);
+ when(source.getRequestURI()).thenReturn("/path/to/resource/search.protobuf");
+ assertThat(request.getMediaType()).isEqualTo(MimeTypes.PROTOBUF);
}
@Test
public void has_param_from_source() {
- when(source.getParameterMap()).thenReturn(ImmutableMap.of("param", new String[]{"value"}));
+ when(source.getParameterMap()).thenReturn(ImmutableMap.of("param", new String[] {"value"}));
ServletRequest request = new ServletRequest(source, Collections.<String, Object>emptyMap());
assertThat(request.hasParam("param")).isTrue();
}
public class WebServiceEngineTest {
- private static class SimpleRequest extends ValidatingRequest {
- private final String method;
- private Map<String, String> params = Maps.newHashMap();
-
- private SimpleRequest(String method) {
- this.method = method;
- }
-
- @Override
- public String method() {
- return method;
- }
-
- @Override
- public String getMediaType() {
- return MimeTypes.JSON;
- }
-
- @Override
- public boolean hasParam(String key) {
- return params.keySet().contains(key);
- }
-
- @Override
- protected String readParam(String key) {
- return params.get(key);
- }
-
- @Override
- protected InputStream readInputStreamParam(String key) {
- String param = readParam(key);
-
- return param == null ? null : IOUtils.toInputStream(param);
- }
-
- public SimpleRequest setParams(Map<String, String> m) {
- this.params = m;
- return this;
- }
-
- public SimpleRequest setParam(String key, @Nullable String value) {
- if (value != null) {
- params.put(key, value);
- }
- return this;
- }
-
- }
-
@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone();
I18n i18n = mock(I18n.class);
assertThat(response.stream().outputAsString()).isEqualTo("good");
}
+ @Test
+ public void execute_request_with_format_type() {
+ ValidatingRequest request = new SimpleRequest("GET");
+ ServletResponse response = new ServletResponse();
+ engine.execute(request, response, "api/system", "health.protobuf");
+
+ assertThat(response.stream().outputAsString()).isEqualTo("good");
+ }
+
@Test
public void no_content() {
ValidatingRequest request = new SimpleRequest("GET");
assertThat(response.getHeader(name)).isEqualTo(value);
}
+ private static class SimpleRequest extends ValidatingRequest {
+ private final String method;
+ private Map<String, String> params = Maps.newHashMap();
+
+ private SimpleRequest(String method) {
+ this.method = method;
+ }
+
+ @Override
+ public String method() {
+ return method;
+ }
+
+ @Override
+ public String getMediaType() {
+ return MimeTypes.JSON;
+ }
+
+ @Override
+ public boolean hasParam(String key) {
+ return params.keySet().contains(key);
+ }
+
+ @Override
+ protected String readParam(String key) {
+ return params.get(key);
+ }
+
+ @Override
+ protected InputStream readInputStreamParam(String key) {
+ String param = readParam(key);
+
+ return param == null ? null : IOUtils.toInputStream(param);
+ }
+
+ public SimpleRequest setParams(Map<String, String> m) {
+ this.params = m;
+ return this;
+ }
+
+ public SimpleRequest setParam(String key, @Nullable String value) {
+ if (value != null) {
+ params.put(key, value);
+ }
+ return this;
+ }
+
+ }
+
static class SystemWs implements WebService {
@Override
public void define(Context context) {
});
newController.done();
}
+
}
}