@@ -12,7 +12,6 @@ configurations { | |||
dependencies { | |||
// please keep list ordered | |||
compile 'com.google.guava:guava' | |||
compile 'com.google.protobuf:protobuf-java' | |||
compile 'com.squareup.okhttp3:okhttp' | |||
compile 'commons-io:commons-io' |
@@ -19,12 +19,13 @@ | |||
*/ | |||
package org.sonarqube.ws; | |||
import com.google.common.base.Strings; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.HashMap; | |||
import java.util.Locale; | |||
import java.util.Map; | |||
import org.apache.commons.io.FilenameUtils; | |||
import static org.sonarqube.ws.WsUtils.isNullOrEmpty; | |||
/** | |||
* @since 5.3 | |||
*/ | |||
@@ -40,36 +41,38 @@ public final class MediaTypes { | |||
public static final String DEFAULT = "application/octet-stream"; | |||
public static final String SVG = "image/svg+xml"; | |||
private static final Map<String, String> MAP = new ImmutableMap.Builder<String, String>() | |||
.put("js", JAVASCRIPT) | |||
.put("json", JSON) | |||
.put("zip", ZIP) | |||
.put("tgz", "application/tgz") | |||
.put("ps", "application/postscript") | |||
.put("jnlp", "application/jnlp") | |||
.put("jar", "application/java-archive") | |||
.put("xls", "application/vnd.ms-excel") | |||
.put("ppt", "application/vnd.ms-powerpoint") | |||
.put("tar", "application/x-tar") | |||
.put("xml", XML) | |||
.put("dtd", "application/xml-dtd") | |||
.put("xslt", "application/xslt+xml") | |||
.put("bmp", "image/bmp") | |||
.put("gif", "image/gif") | |||
.put("jpg", "image/jpeg") | |||
.put("jpeg", "image/jpeg") | |||
.put("tiff", "image/tiff") | |||
.put("png", "image/png") | |||
.put("svg", SVG) | |||
.put("ico", "image/x-icon") | |||
.put("txt", TXT) | |||
.put("csv", "text/csv") | |||
.put("properties", TXT) | |||
.put("rtf", "text/rtf") | |||
.put("html", HTML) | |||
.put("css", "text/css") | |||
.put("tsv", "text/tab-separated-values") | |||
.build(); | |||
private static final Map<String, String> MAP = new HashMap<>(); | |||
static { | |||
MAP.put("js", JAVASCRIPT); | |||
MAP.put("json", JSON); | |||
MAP.put("zip", ZIP); | |||
MAP.put("tgz", "application/tgz"); | |||
MAP.put("ps", "application/postscript"); | |||
MAP.put("jnlp", "application/jnlp"); | |||
MAP.put("jar", "application/java-archive"); | |||
MAP.put("xls", "application/vnd.ms-excel"); | |||
MAP.put("ppt", "application/vnd.ms-powerpoint"); | |||
MAP.put("tar", "application/x-tar"); | |||
MAP.put("xml", XML); | |||
MAP.put("dtd", "application/xml-dtd"); | |||
MAP.put("xslt", "application/xslt+xml"); | |||
MAP.put("bmp", "image/bmp"); | |||
MAP.put("gif", "image/gif"); | |||
MAP.put("jpg", "image/jpeg"); | |||
MAP.put("jpeg", "image/jpeg"); | |||
MAP.put("tiff", "image/tiff"); | |||
MAP.put("png", "image/png"); | |||
MAP.put("svg", SVG); | |||
MAP.put("ico", "image/x-icon"); | |||
MAP.put("txt", TXT); | |||
MAP.put("csv", "text/csv"); | |||
MAP.put("properties", TXT); | |||
MAP.put("rtf", "text/rtf"); | |||
MAP.put("html", HTML); | |||
MAP.put("css", "text/css"); | |||
MAP.put("tsv", "text/tab-separated-values"); | |||
} | |||
private MediaTypes() { | |||
// only static methods | |||
@@ -78,7 +81,7 @@ public final class MediaTypes { | |||
public static String getByFilename(String filename) { | |||
String extension = FilenameUtils.getExtension(filename); | |||
String mime = null; | |||
if (!Strings.isNullOrEmpty(extension)) { | |||
if (!isNullOrEmpty(extension)) { | |||
mime = MAP.get(extension.toLowerCase(Locale.ENGLISH)); | |||
} | |||
return mime != null ? mime : DEFAULT; |
@@ -0,0 +1,52 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info 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; | |||
import javax.annotation.Nullable; | |||
import static java.lang.String.format; | |||
public class WsUtils { | |||
private WsUtils() { | |||
// Only static methods here | |||
} | |||
public static void checkArgument(boolean expression) { | |||
if (!expression) { | |||
throw new IllegalArgumentException(); | |||
} | |||
} | |||
public static void checkArgument(boolean expression, String message, Object... args) { | |||
if (!expression) { | |||
throw new IllegalArgumentException(format(message, args)); | |||
} | |||
} | |||
public static boolean isNullOrEmpty(@Nullable String string) { | |||
return string == null || string.length() == 0; | |||
} | |||
public static String nullToEmpty(@Nullable String string) { | |||
return string == null ? "" : string; | |||
} | |||
} |
@@ -19,8 +19,7 @@ | |||
*/ | |||
package org.sonarqube.ws.client; | |||
import com.google.common.collect.LinkedListMultimap; | |||
import com.google.common.collect.ListMultimap; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashMap; | |||
import java.util.LinkedHashMap; | |||
@@ -36,11 +35,11 @@ import javax.annotation.CheckForNull; | |||
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.Collections.singletonList; | |||
import static java.util.Collections.emptyList; | |||
import static java.util.Collections.unmodifiableSet; | |||
import static java.util.Objects.requireNonNull; | |||
import static org.sonarqube.ws.WsUtils.checkArgument; | |||
import static org.sonarqube.ws.WsUtils.isNullOrEmpty; | |||
abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest { | |||
@@ -163,7 +162,7 @@ abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest { | |||
private static class DefaultParameters implements Parameters { | |||
// preserve insertion order | |||
private final ListMultimap<String, String> keyValues = LinkedListMultimap.create(); | |||
private final Map<String, List<String>> keyValues = new LinkedHashMap<>(); | |||
@Override | |||
@CheckForNull | |||
@@ -173,7 +172,7 @@ abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest { | |||
@Override | |||
public List<String> getValues(String key) { | |||
return keyValues.get(key); | |||
return keyValues.containsKey(key) ? keyValues.get(key) : emptyList(); | |||
} | |||
@Override | |||
@@ -185,7 +184,7 @@ abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest { | |||
checkArgument(!isNullOrEmpty(key)); | |||
checkArgument(value != null); | |||
keyValues.putAll(key, singletonList(value)); | |||
keyValues.computeIfAbsent(key, k -> new ArrayList<>()).add(value); | |||
return this; | |||
} | |||
@@ -193,8 +192,7 @@ abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest { | |||
checkArgument(!isNullOrEmpty(key)); | |||
checkArgument(values != null && !values.isEmpty()); | |||
this.keyValues.putAll(key, values.stream().map(Object::toString).filter(Objects::nonNull).collect(Collectors.toList())); | |||
keyValues.computeIfAbsent(key, k -> new ArrayList<>()).addAll(values.stream().map(Object::toString).filter(Objects::nonNull).collect(Collectors.toList())); | |||
return this; | |||
} | |||
} |
@@ -28,8 +28,8 @@ import javax.annotation.Nullable; | |||
import org.apache.commons.io.IOUtils; | |||
import org.sonarqube.ws.MediaTypes; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static com.google.common.base.Strings.isNullOrEmpty; | |||
import static org.sonarqube.ws.WsUtils.checkArgument; | |||
import static org.sonarqube.ws.WsUtils.isNullOrEmpty; | |||
public abstract class BaseService { | |||
@@ -37,7 +37,7 @@ public abstract class BaseService { | |||
protected final String controller; | |||
public BaseService(WsConnector wsConnector, String controllerPath) { | |||
checkArgument(!isNullOrEmpty(controllerPath)); | |||
checkArgument(!isNullOrEmpty(controllerPath), "Controller path cannot be empty"); | |||
this.wsConnector = wsConnector; | |||
this.controller = controllerPath; | |||
} |
@@ -37,15 +37,15 @@ import okhttp3.Request; | |||
import okhttp3.RequestBody; | |||
import okhttp3.Response; | |||
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; | |||
import static java.net.HttpURLConnection.HTTP_MOVED_PERM; | |||
import static java.net.HttpURLConnection.HTTP_MOVED_TEMP; | |||
import static java.nio.charset.StandardCharsets.UTF_8; | |||
import static okhttp3.internal.http.StatusLine.HTTP_PERM_REDIRECT; | |||
import static okhttp3.internal.http.StatusLine.HTTP_TEMP_REDIRECT; | |||
import static org.sonarqube.ws.WsUtils.checkArgument; | |||
import static org.sonarqube.ws.WsUtils.isNullOrEmpty; | |||
import static org.sonarqube.ws.WsUtils.nullToEmpty; | |||
/** | |||
* Connect to any SonarQube server available through HTTP or HTTPS. |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonarqube.ws.client; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.InputStream; | |||
import java.io.InputStreamReader; | |||
@@ -41,7 +40,6 @@ class LocalWsConnector implements WsConnector { | |||
this.localConnector = localConnector; | |||
} | |||
@VisibleForTesting | |||
LocalConnector localConnector() { | |||
return localConnector; | |||
} |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonarqube.ws.client; | |||
import com.google.common.base.Throwables; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
@@ -78,7 +77,7 @@ public class MockWsResponse extends BaseResponse { | |||
try { | |||
return setContent(IOUtils.toByteArray(is)); | |||
} catch (IOException e) { | |||
throw Throwables.propagate(e); | |||
throw new IllegalArgumentException(e); | |||
} | |||
} | |||
@@ -47,9 +47,9 @@ import okhttp3.OkHttpClient; | |||
import okhttp3.Request; | |||
import okhttp3.Response; | |||
import static com.google.common.base.Strings.nullToEmpty; | |||
import static java.nio.charset.StandardCharsets.UTF_8; | |||
import static java.util.Arrays.asList; | |||
import static org.sonarqube.ws.WsUtils.nullToEmpty; | |||
/** | |||
* Helper to build an instance of {@link okhttp3.OkHttpClient} that |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonarqube.ws.client; | |||
import com.google.common.collect.ImmutableList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import org.assertj.core.data.MapEntry; | |||
@@ -28,7 +27,6 @@ import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonarqube.ws.MediaTypes; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -70,17 +68,17 @@ public class BaseRequestTest { | |||
assertParameters(entry("keyB", "b"), entry("keyA", "a")); | |||
assertMultiValueParameters(entry("keyB", singletonList("b")), entry("keyA", singletonList("a"))); | |||
underTest.setParam("keyC", ImmutableList.of("c1", "c2", "c3")); | |||
underTest.setParam("keyC", asList("c1", "c2", "c3")); | |||
assertParameters(entry("keyB", "b"), entry("keyA", "a"), entry("keyC", "c1")); | |||
assertMultiValueParameters( | |||
entry("keyB", singletonList("b")), | |||
entry("keyA", singletonList("a")), | |||
entry("keyC", ImmutableList.of("c1", "c2", "c3"))); | |||
entry("keyC", asList("c1", "c2", "c3"))); | |||
} | |||
@Test | |||
public void skip_null_value_in_multi_param() { | |||
underTest.setParam("key", newArrayList("v1", null, "", "v3")); | |||
underTest.setParam("key", asList("v1", null, "", "v3")); | |||
assertMultiValueParameters(entry("key", asList("v1", "", "v3"))); | |||
} |
@@ -19,9 +19,9 @@ | |||
*/ | |||
package org.sonarqube.ws.client; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.apache.commons.io.IOUtils; | |||
@@ -57,7 +57,9 @@ public class LocalWsConnectorTest { | |||
WsResponse wsResponse = underTest.call(wsRequest); | |||
verifyRequested("POST", "api/issues/search", MediaTypes.JSON, ImmutableMap.of("foo", "bar")); | |||
Map<String, String> expectedParams = new HashMap<>(); | |||
expectedParams.put("foo", "bar"); | |||
verifyRequested("POST", "api/issues/search", MediaTypes.JSON, expectedParams); | |||
assertThat(wsResponse.code()).isEqualTo(400); | |||
assertThat(wsResponse.content()).isEqualTo("{}"); | |||
assertThat(IOUtils.toString(wsResponse.contentReader())).isEqualTo("{}"); |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonarqube.ws.client; | |||
import com.google.common.base.Joiner; | |||
import com.google.protobuf.Parser; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
@@ -89,7 +88,6 @@ import static org.mockito.Mockito.spy; | |||
* | |||
*/ | |||
public class ServiceTester<T extends BaseService> extends ExternalResource { | |||
private static final Joiner COMMA_JOINER = Joiner.on(","); | |||
private final T underTest; | |||
private final List<GetCall> getCalls = new ArrayList<>(); |