diff --git a/src/main/java/se/michaelthelin/spotify/Base64.java b/src/main/java/se/michaelthelin/spotify/Base64.java index 124e5c533..a804f01e5 100644 --- a/src/main/java/se/michaelthelin/spotify/Base64.java +++ b/src/main/java/se/michaelthelin/spotify/Base64.java @@ -1,18 +1,38 @@ package se.michaelthelin.spotify; import java.io.ByteArrayOutputStream; +import java.util.Arrays; /** - * Source: https://gist.github.com/EmilHernvall/953733#file-base64-java - * Due to Java version support issues with Datatypeconverter (<=1.7) class and Base64 (>=1.8) class. + * Source: EmilHernvall/Base64.java + * Due to Java version support issues with DataTypeConverter (<=1.7) class and Base64 (>=1.8) class. */ public class Base64 { + private static final char[] ENCODE_TABLE_BASE = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; + + private static final int[] DECODE_TABLE_BASE = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + public static String encode(byte[] data) { - char[] tbl = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; + char[] tbl = Arrays.copyOf(ENCODE_TABLE_BASE, ENCODE_TABLE_BASE.length); StringBuilder buffer = new StringBuilder(); int pad = 0; @@ -44,22 +64,8 @@ public static String encode(byte[] data) { } public static byte[] decode(String data) { - int[] tbl = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + int[] tbl = Arrays.copyOf(DECODE_TABLE_BASE, DECODE_TABLE_BASE.length); + byte[] bytes = data.getBytes(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); for (int i = 0; i < bytes.length; ) { diff --git a/src/main/java/se/michaelthelin/spotify/SpotifyHttpRequestRetryStrategy.java b/src/main/java/se/michaelthelin/spotify/SpotifyHttpRequestRetryStrategy.java index 9eceb57c2..5f28a9391 100644 --- a/src/main/java/se/michaelthelin/spotify/SpotifyHttpRequestRetryStrategy.java +++ b/src/main/java/se/michaelthelin/spotify/SpotifyHttpRequestRetryStrategy.java @@ -149,8 +149,8 @@ public boolean retryRequest( final IOException exception, final int execCount, final HttpContext context) { - Args.notNull(request, "request"); - Args.notNull(exception, "exception"); + Objects.requireNonNull(request, "request"); + Objects.requireNonNull(exception, "exception"); if (execCount > this.maxRetries) { // Do not retry if over max retries @@ -178,7 +178,7 @@ public boolean retryRequest( final HttpResponse response, final int execCount, final HttpContext context) { - Args.notNull(response, "response"); + Objects.requireNonNull(response, "response"); return execCount <= this.maxRetries && retriableCodes.contains(response.getCode()); } @@ -188,7 +188,7 @@ public TimeValue getRetryInterval( final HttpResponse response, final int execCount, final HttpContext context) { - Args.notNull(response, "response"); + Objects.requireNonNull(response, "response"); return this.defaultRetryInterval; } diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/IPlaylistItem.java b/src/main/java/se/michaelthelin/spotify/model_objects/IPlaylistItem.java index d54493341..aef681ea7 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/IPlaylistItem.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/IPlaylistItem.java @@ -17,7 +17,7 @@ public interface IPlaylistItem extends IModelObject { * * @return The playlist item length in milliseconds. */ - public Integer getDurationMs(); + Integer getDurationMs(); /** * Get the external URLs of the playlist item.
@@ -25,14 +25,14 @@ public interface IPlaylistItem extends IModelObject { * * @return Known external URLs for this playlist item. */ - public ExternalUrl getExternalUrls(); + ExternalUrl getExternalUrls(); /** * Get the full Spotify Web API endpoint URL of the playlist item. * * @return A link to the Web API endpoint providing full details of the playlist item. */ - public String getHref(); + String getHref(); /** * Get the Spotify ID of the @@ -40,14 +40,14 @@ public interface IPlaylistItem extends IModelObject { * * @return The Spotify ID for the playlist item. */ - public String getId(); + String getId(); /** * Get the name of the playlist item. * * @return playlist item name. */ - public String getName(); + String getName(); /** * Get the type of the IPlaylistItem. @@ -63,5 +63,5 @@ public interface IPlaylistItem extends IModelObject { * @return The Spotify URI for * the playlist item. */ - public String getUri(); + String getUri(); } diff --git a/src/main/java/se/michaelthelin/spotify/model_objects/utils/PlaylistItemFactory.java b/src/main/java/se/michaelthelin/spotify/model_objects/utils/PlaylistItemFactory.java index c779a100a..75832b572 100644 --- a/src/main/java/se/michaelthelin/spotify/model_objects/utils/PlaylistItemFactory.java +++ b/src/main/java/se/michaelthelin/spotify/model_objects/utils/PlaylistItemFactory.java @@ -7,7 +7,7 @@ import se.michaelthelin.spotify.model_objects.specification.Track; public class PlaylistItemFactory { - private static final JsonUtil jsonUtil = new JsonUtil() { + private static final JsonUtil jsonUtil = new JsonUtil<>() { @Override public Object createModelObject(JsonObject jsonObject) { return null; diff --git a/src/test/java/se/michaelthelin/spotify/Base64Test.java b/src/test/java/se/michaelthelin/spotify/Base64Test.java new file mode 100644 index 000000000..519fcb75b --- /dev/null +++ b/src/test/java/se/michaelthelin/spotify/Base64Test.java @@ -0,0 +1,20 @@ +package se.michaelthelin.spotify; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class Base64Test { + private static final String BASE_64_TEST_DATA = "Hello World"; + private static final String BASE_64_TEST_DATA_ENCODED = "SGVsbG8gV29ybGQ="; + + @Test + public void testCustomBase64() { + byte[] testDataBytes = BASE_64_TEST_DATA.getBytes(); + + String encoded = Base64.encode(testDataBytes); + Assertions.assertEquals(BASE_64_TEST_DATA_ENCODED, encoded); + + byte[] decoded = Base64.decode(encoded); + Assertions.assertArrayEquals(testDataBytes, decoded); + } +} diff --git a/src/test/java/se/michaelthelin/spotify/TestDefaultHttpRequestRetryStrategy.java b/src/test/java/se/michaelthelin/spotify/TestDefaultHttpRequestRetryStrategy.java index 0ff00ff39..3f0d30c8e 100644 --- a/src/test/java/se/michaelthelin/spotify/TestDefaultHttpRequestRetryStrategy.java +++ b/src/test/java/se/michaelthelin/spotify/TestDefaultHttpRequestRetryStrategy.java @@ -87,7 +87,7 @@ public void testRetryAfterHeaderAsDate() { final HttpResponse response = new BasicHttpResponse(503, "Oopsie"); response.setHeader(HttpHeaders.RETRY_AFTER, DateUtils.formatStandardDate(Instant.now().plus(100, ChronoUnit.SECONDS))); - Assertions.assertTrue(this.retryStrategy.getRetryInterval(response, 3, null).compareTo(TimeValue.ZERO_MILLISECONDS) == 0); + Assertions.assertEquals(0, this.retryStrategy.getRetryInterval(response, 3, null).compareTo(TimeValue.ZERO_MILLISECONDS)); } @Test diff --git a/src/test/java/se/michaelthelin/spotify/TestUtil.java b/src/test/java/se/michaelthelin/spotify/TestUtil.java index 54bc3fb59..59a597c62 100644 --- a/src/test/java/se/michaelthelin/spotify/TestUtil.java +++ b/src/test/java/se/michaelthelin/spotify/TestUtil.java @@ -6,6 +6,7 @@ import java.io.*; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.logging.Level; import static org.mockito.ArgumentMatchers.nullable; @@ -21,7 +22,7 @@ private static String readTestData(String fileName) throws IOException { } private static String readFromFile(File file) throws IOException { - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)); + BufferedReader in = new BufferedReader(new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8)); StringBuilder out = new StringBuilder(); String line; diff --git a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java index 0548524c2..32603f918 100644 --- a/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java +++ b/src/test/java/se/michaelthelin/spotify/requests/data/playlists/GetPlaylistRequestTest.java @@ -1,8 +1,28 @@ package se.michaelthelin.spotify.requests.data.playlists; -import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + import org.apache.hc.core5.http.ParseException; import org.junit.jupiter.api.Test; + +import com.github.tomakehurst.wiremock.junit5.WireMockTest; + import se.michaelthelin.spotify.ITest; import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.SpotifyHttpManager; @@ -13,12 +33,6 @@ import se.michaelthelin.spotify.model_objects.specification.Playlist; import se.michaelthelin.spotify.requests.data.AbstractDataTest; -import java.io.IOException; -import java.util.concurrent.*; - -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static org.junit.jupiter.api.Assertions.*; - @WireMockTest(httpPort = 9090) public class GetPlaylistRequestTest extends AbstractDataTest { private final GetPlaylistRequest defaultRequest = ITest.SPOTIFY_API @@ -35,7 +49,7 @@ public GetPlaylistRequestTest() throws Exception { } @Test - public void shouldThrowTooManyRequestExceptionAndNotBlockThread_WhenSpotifyReturns429() throws IOException, ParseException, SpotifyWebApiException { + public void shouldThrowTooManyRequestExceptionAndNotBlockThread_WhenSpotifyReturns429() { SpotifyApi spotifyApi = new SpotifyApi.Builder() .setScheme("http") .setHost("localhost") @@ -62,7 +76,7 @@ public void shouldThrowTooManyRequestExceptionAndNotBlockThread_WhenSpotifyRetur try { Future submit = executor.submit(playlistCall); - Playlist playlist = submit.get(10, TimeUnit.SECONDS); + submit.get(10, TimeUnit.SECONDS); } catch (ExecutionException e) { assertEquals(e.getCause().getClass(), TooManyRequestsException.class); } catch (TimeoutException | InterruptedException e) {