diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index ebeda33fcb..bad2eb639c 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -17,3 +17,4 @@ af9205fa592e4ae32ceca951c560a48b512b7744 f58dd73747791edcd45722a4903da44da1b9b2d3 fcdaa3d6735d2382a44d066a6ce051a2c5e6469f 9bbe16b7d1600fc96100f54cb25869cbdf425521 +3addaca346bcdfd555fca0340e40c7e5518c5185 diff --git a/allowed-licenses.json b/allowed-licenses.json index 5b412832ea..27e65ce272 100644 --- a/allowed-licenses.json +++ b/allowed-licenses.json @@ -20,6 +20,10 @@ "moduleLicense": null, "moduleName": "com.squareup.okio:okio" }, + { + "moduleLicense": null, + "moduleName": "com.squareup.okhttp3:okhttp" + }, { "moduleLicense": null, "moduleName": "com.netflix.graphql.dgs:graphql-dgs-platform" diff --git a/commercetools/commercetools-okhttp-client5/build.gradle b/commercetools/commercetools-okhttp-client5/build.gradle new file mode 100644 index 0000000000..c1bd76b7a9 --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/build.gradle @@ -0,0 +1,21 @@ +apply plugin: "me.champeau.jmh" + +jmh { + iterations = 5 + benchmarkMode = ['thrpt'] + threads = 25 + fork = 3 + timeOnIteration = '1s' + profilers = ['gc'] +} + +dependencies { + api project(":rmf:rmf-java-base") + api "com.squareup.okhttp3:okhttp:5.3.2" version { + strictly '[5.0,5.99999]' + prefer "5.3.2" + } + implementation "com.squareup.okio:okio:3.16.2" + + implementation javax.validation +} diff --git a/commercetools/commercetools-okhttp-client5/src/jmh/java/com/commercetools/http/okhttp4/UnzipBenchmark.java b/commercetools/commercetools-okhttp-client5/src/jmh/java/com/commercetools/http/okhttp4/UnzipBenchmark.java new file mode 100644 index 0000000000..79400a11a3 --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/jmh/java/com/commercetools/http/okhttp4/UnzipBenchmark.java @@ -0,0 +1,120 @@ + +package com.commercetools.http.okhttp5; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.zip.GZIPOutputStream; + +import io.vrap.rmf.base.client.ApiHttpResponse; + +import org.assertj.core.api.Assertions; +import org.openjdk.jmh.annotations.*; + +import okhttp3.*; +import okio.Okio; + +public class UnzipBenchmark { + + @State(Scope.Benchmark) + public static class InterceptorState { + private CtOkHttp5Client.UnzippingInterceptor interceptor; + + @Setup(Level.Trial) + public void init() { + interceptor = new CtOkHttp5Client.UnzippingInterceptor(); + printUsedMemory(); + + } + + @TearDown(Level.Trial) + public void tearDown() { + printUsedMemory(); + } + } + @Benchmark + public void unzip(InterceptorState state) throws IOException { + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + GZIPOutputStream gzipOs = new GZIPOutputStream(os); + byte[] buffer = "Sample Text".getBytes(); + gzipOs.write(buffer, 0, buffer.length); + gzipOs.close(); + ByteArrayInputStream inputStream = new ByteArrayInputStream(os.toByteArray()); + + Response gzipped = new Response.Builder().request(new Request.Builder().url("http://localhost").build()) + .protocol(Protocol.HTTP_1_1) + .addHeader("content-encoding", "gzip") + .addHeader("content-type", "application/json") + .code(200) + .message("Ok") + .body(ResponseBody.create(MediaType.parse("application/json"), -1L, + Okio.buffer(Okio.source(inputStream)))) + .build(); + Assertions.assertThat(gzipped.body().source().isOpen()).isTrue(); + + Response unzipped = state.interceptor.unzip(gzipped); + + Assertions.assertThat(gzipped.body().source().isOpen()).isTrue(); + Assertions.assertThat(unzipped.body().source().isOpen()).isTrue(); + Assertions.assertThat(inputStream.available()).isEqualTo(31); + + ApiHttpResponse response = CtOkHttp5Client.toResponse(unzipped); + + Assertions.assertThat(gzipped.body().source().isOpen()).isFalse(); + Assertions.assertThat(unzipped.body().source().isOpen()).isFalse(); + Assertions.assertThat(inputStream.available()).isEqualTo(0); + + String text = new String(response.getBody(), StandardCharsets.UTF_8); + Assertions.assertThat(text).isEqualTo("Sample Text"); + } + + public static void printUsedMemory() { + long _usedMem; + long _total; + long _total2; + long _count = -1; + System.out.flush(); + // loop to get a stable reading, since memory may be resized between the method calls + do { + _count++; + _total = Runtime.getRuntime().totalMemory(); + try { + Thread.sleep(12); + } + catch (Exception ignore) { + } + long _free = Runtime.getRuntime().freeMemory(); + _total2 = Runtime.getRuntime().totalMemory(); + _usedMem = _total - _free; + } while (_total != _total2); + System.out.println("before GC: used=" + _usedMem + ", loopCount=" + _count + ", total=" + _total); + try { + Runtime.getRuntime().gc(); + Thread.sleep(55); + Runtime.getRuntime().gc(); + Thread.sleep(55); + Runtime.getRuntime().gc(); + Thread.sleep(55); + Runtime.getRuntime().gc(); + Thread.sleep(55); + } + catch (Exception ignore) { + } + // loop to get a stable reading, since memory may be resized between the method calls + do { + _count++; + _total = Runtime.getRuntime().totalMemory(); + try { + Thread.sleep(12); + } + catch (Exception ignore) { + } + long _free = Runtime.getRuntime().freeMemory(); + _total2 = Runtime.getRuntime().totalMemory(); + _usedMem = _total - _free; + } while (_total != _total2); + System.out.println("after GC: used=" + _usedMem + ", loopCount=" + _count + ", total=" + _total); + } +} diff --git a/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/BuilderOptions.java b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/BuilderOptions.java new file mode 100644 index 0000000000..079137c451 --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/BuilderOptions.java @@ -0,0 +1,9 @@ + +package com.commercetools.http.okhttp5; + +import okhttp3.OkHttpClient; + +@FunctionalInterface +public interface BuilderOptions { + OkHttpClient.Builder plus(OkHttpClient.Builder builder); +} diff --git a/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/CtOkHttp5Client.java b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/CtOkHttp5Client.java new file mode 100644 index 0000000000..d9565277da --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/CtOkHttp5Client.java @@ -0,0 +1,226 @@ + +package com.commercetools.http.okhttp5; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import io.vrap.rmf.base.client.*; +import io.vrap.rmf.base.client.utils.Utils; + +import jakarta.validation.constraints.NotNull; +import okhttp3.OkHttpClient; +import okio.GzipSource; +import okio.Okio; + +public class CtOkHttp5Client extends HttpClientBase { + + public static final int MAX_REQUESTS = 64; + private final Supplier clientBuilder = () -> new OkHttpClient.Builder() + .connectTimeout(120, TimeUnit.SECONDS) + .writeTimeout(120, TimeUnit.SECONDS) + .readTimeout(120, TimeUnit.SECONDS) + .protocols(Collections.singletonList(okhttp3.Protocol.HTTP_1_1)) + .addInterceptor(new UnzippingInterceptor()); + + private final OkHttpClient okHttpClient; + + public CtOkHttp5Client() { + super(); + okHttpClient = clientBuilder.get().dispatcher(createDispatcher(MAX_REQUESTS, MAX_REQUESTS)).build(); + } + + public CtOkHttp5Client(final BuilderOptions options) { + super(); + okHttpClient = options.plus(clientBuilder.get().dispatcher(createDispatcher(MAX_REQUESTS, MAX_REQUESTS))) + .build(); + } + + public CtOkHttp5Client(final Supplier builderSupplier) { + super(); + okHttpClient = builderSupplier.get().build(); + } + + public CtOkHttp5Client(final int maxRequests, final int maxRequestsPerHost) { + super(); + okHttpClient = clientBuilder.get().dispatcher(createDispatcher(maxRequests, maxRequestsPerHost)).build(); + } + + public CtOkHttp5Client(final int maxRequests, final int maxRequestsPerHost, final BuilderOptions options) { + super(); + okHttpClient = options.plus(clientBuilder.get().dispatcher(createDispatcher(maxRequests, maxRequestsPerHost))) + .build(); + } + + public CtOkHttp5Client(final ExecutorService executor) { + super(executor); + okHttpClient = clientBuilder.get().dispatcher(createDispatcher(executor, MAX_REQUESTS, MAX_REQUESTS)).build(); + } + + public CtOkHttp5Client(final ExecutorService executor, final BuilderOptions options) { + super(executor); + okHttpClient = options.plus(clientBuilder.get().dispatcher(createDispatcher(MAX_REQUESTS, MAX_REQUESTS))) + .build(); + } + + public CtOkHttp5Client(final ExecutorService executor, final int maxRequests, final int maxRequestsPerHost) { + super(executor); + okHttpClient = clientBuilder.get() + .dispatcher(createDispatcher(executor, maxRequests, maxRequestsPerHost)) + .build(); + } + + public CtOkHttp5Client(final ExecutorService executor, final int maxRequests, final int maxRequestsPerHost, + final BuilderOptions options) { + super(executor); + okHttpClient = options + .plus(clientBuilder.get().dispatcher(createDispatcher(executor, maxRequests, maxRequestsPerHost))) + .build(); + } + + public okhttp3.Dispatcher createDispatcher(final int maxRequests, final int maxRequestsPerHost) { + final okhttp3.Dispatcher dispatcher = new okhttp3.Dispatcher(); + dispatcher.setMaxRequests(maxRequests); + dispatcher.setMaxRequestsPerHost(maxRequestsPerHost); + return dispatcher; + } + + public okhttp3.Dispatcher createDispatcher(final ExecutorService executor, final int maxRequests, + final int maxRequestsPerHost) { + final okhttp3.Dispatcher dispatcher = new okhttp3.Dispatcher(executor); + dispatcher.setMaxRequests(maxRequests); + dispatcher.setMaxRequestsPerHost(maxRequestsPerHost); + return dispatcher; + } + + private static final String CONTENT_TYPE = "Content-Type"; + private static final okhttp3.MediaType JSON = okhttp3.MediaType.get("application/json; charset=utf-8"); + private static final byte[] emptyBody = new byte[0]; + + @Override + public CompletableFuture> execute(final ApiHttpRequest request) { + return makeRequest(okHttpClient, toRequest(request)).thenApplyAsync(CtOkHttp5Client::toResponse, executor()); + + } + + static ApiHttpResponse toResponse(final okhttp3.Response response) { + final ApiHttpHeaders apiHttpHeaders = new ApiHttpHeaders(response.headers() + .toMultimap() + .entrySet() + .stream() + .flatMap(e -> e.getValue().stream().map(value -> ApiHttpHeaders.headerEntry(e.getKey(), value))) + .collect(Collectors.toList())); + + final ApiHttpResponse apiHttpResponse = new ApiHttpResponse<>(response.code(), apiHttpHeaders, + Optional.ofNullable(response.body()) + .map(Utils.wrapToCompletionException(okhttp3.ResponseBody::bytes)) + .orElse(null), + response.message()); + if (response.body() != null) { + response.close(); + } + return apiHttpResponse; + } + + private static okhttp3.Request toRequest(final ApiHttpRequest apiHttpRequest) { + + okhttp3.Request.Builder httpRequestBuilder = new okhttp3.Request.Builder().url(apiHttpRequest.getUrl()); + + //set headers + for (Map.Entry entry : apiHttpRequest.getHeaders().getHeaders()) { + httpRequestBuilder = httpRequestBuilder.header(entry.getKey(), entry.getValue()); + } + + if (apiHttpRequest.getMethod() == null) { + throw new IllegalStateException("apiHttpRequest method should be non null"); + } + + //default media type is JSON, if other media type is set as a header, use it + okhttp3.MediaType mediaType = JSON; + if (apiHttpRequest.getHeaders() + .getHeaders() + .stream() + .anyMatch(s -> s.getKey().equalsIgnoreCase(CONTENT_TYPE))) { + mediaType = okhttp3.MediaType + .get(Objects.requireNonNull(apiHttpRequest.getHeaders().getFirst(ApiHttpHeaders.CONTENT_TYPE))); + } + + try { + final okhttp3.RequestBody body = apiHttpRequest.getBody() == null ? null + : okhttp3.RequestBody.create(apiHttpRequest.getBody(), mediaType); + httpRequestBuilder.method(apiHttpRequest.getMethod().name(), body); + } + catch (NoSuchMethodError error) { + throw new IllegalStateException( + "Request class is not compatible with this HTTP client implementation. Probably a wrong http client package is used. Please try \"commercetools-okhttp-client3\" instead"); + } + return httpRequestBuilder.build(); + } + + private CompletableFuture makeRequest(final OkHttpClient client, final okhttp3.Request request) { + final okhttp3.Call call = client.newCall(request); + final OkHttpResponseFuture result = new OkHttpResponseFuture(); + call.enqueue(result); + return result.future; + } + + private static class OkHttpResponseFuture implements okhttp3.Callback { + public final CompletableFuture future = new CompletableFuture<>(); + + public OkHttpResponseFuture() { + } + + @Override + public void onFailure(final okhttp3.Call call, final IOException e) { + future.completeExceptionally(e); + } + + @Override + public void onResponse(final okhttp3.Call call, final okhttp3.Response response) throws IOException { + future.complete(response); + } + } + + @Override + public void closeDelegate() throws IOException { + okHttpClient.dispatcher().executorService().shutdown(); + okHttpClient.connectionPool().evictAll(); + if (okHttpClient.cache() != null) + Objects.requireNonNull(okHttpClient.cache()).close(); + } + + public static class UnzippingInterceptor implements okhttp3.Interceptor { + @Override + @NotNull + public okhttp3.Response intercept(Chain chain) throws IOException { + okhttp3.Response response = chain.proceed(chain.request()); + return unzip(response); + } + + okhttp3.Response unzip(final okhttp3.Response response) { + if (!"gzip".equalsIgnoreCase(response.header("Content-Encoding"))) { + return response; + } + + if (response.body() == null) { + return response; + } + + okhttp3.Headers strippedHeaders = response.headers() + .newBuilder() + .removeAll("Content-Encoding") + .removeAll("Content-Length") + .build(); + String contentType = response.header("Content-Type"); + return response.newBuilder() + .headers(strippedHeaders) + .body(okhttp3.ResponseBody.create(Okio.buffer(new GzipSource(response.body().source())), + okhttp3.MediaType.get(contentType), -1L)) + .build(); + } + } +} diff --git a/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/OkHttp5ClientSupplier.java b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/OkHttp5ClientSupplier.java new file mode 100644 index 0000000000..0ac1774bc8 --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/OkHttp5ClientSupplier.java @@ -0,0 +1,21 @@ + +package com.commercetools.http.okhttp5; + +import java.util.concurrent.ExecutorService; +import java.util.function.Supplier; + +import io.vrap.rmf.base.client.BaseHttpClientSupplier; +import io.vrap.rmf.base.client.VrapHttpClient; + +public class OkHttp5ClientSupplier extends BaseHttpClientSupplier { + + @Override + public VrapHttpClient get() { + return new CtOkHttp5Client(); + } + + @Override + public Supplier get(ExecutorService executorService) { + return () -> new CtOkHttp5Client(executorService); + } +} diff --git a/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/OkHttpClientSolutionInfo.java b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/OkHttpClientSolutionInfo.java new file mode 100644 index 0000000000..affbc0b8f8 --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/main/java/com/commercetools/http/okhttp5/OkHttpClientSolutionInfo.java @@ -0,0 +1,14 @@ + +package com.commercetools.http.okhttp5; + +import io.vrap.rmf.base.client.SolutionInfo; + +import okhttp3.OkHttp; + +public class OkHttpClientSolutionInfo extends SolutionInfo { + + public OkHttpClientSolutionInfo() { + setName("OkHttpClient"); + setVersion(OkHttp.VERSION); + } +} diff --git a/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.ExecutorHttpClientSupplier b/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.ExecutorHttpClientSupplier new file mode 100644 index 0000000000..2f4a83f0cf --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.ExecutorHttpClientSupplier @@ -0,0 +1 @@ +com.commercetools.http.okhttp5.OkHttp5ClientSupplier diff --git a/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.HttpClientSupplier b/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.HttpClientSupplier new file mode 100644 index 0000000000..2f4a83f0cf --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.HttpClientSupplier @@ -0,0 +1 @@ +com.commercetools.http.okhttp5.OkHttp5ClientSupplier diff --git a/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.SolutionInfo b/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.SolutionInfo new file mode 100644 index 0000000000..300da03a52 --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/main/resources/META-INF/services/io.vrap.rmf.base.client.SolutionInfo @@ -0,0 +1 @@ +com.commercetools.http.okhttp5.OkHttpClientSolutionInfo diff --git a/commercetools/commercetools-okhttp-client5/src/test/java/com/commercetools/http/okhttp5/SolutionInfoTest.java b/commercetools/commercetools-okhttp-client5/src/test/java/com/commercetools/http/okhttp5/SolutionInfoTest.java new file mode 100644 index 0000000000..3671abb028 --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/test/java/com/commercetools/http/okhttp5/SolutionInfoTest.java @@ -0,0 +1,18 @@ + +package com.commercetools.http.okhttp5; + +import com.vdurmont.semver4j.Semver; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +public class SolutionInfoTest { + @Test + public void version() { + String version = new OkHttpClientSolutionInfo().getVersion(); + + Assertions.assertThat(new Semver(version, Semver.SemverType.LOOSE).compareTo(new Semver("5.3.0"))) + .isGreaterThanOrEqualTo(0); + Assertions.assertThat(version).startsWith("5."); + } +} diff --git a/commercetools/commercetools-okhttp-client5/src/test/java/com/commercetools/http/okhttp5/SupplierTest.java b/commercetools/commercetools-okhttp-client5/src/test/java/com/commercetools/http/okhttp5/SupplierTest.java new file mode 100644 index 0000000000..6f2e8af76e --- /dev/null +++ b/commercetools/commercetools-okhttp-client5/src/test/java/com/commercetools/http/okhttp5/SupplierTest.java @@ -0,0 +1,63 @@ + +package com.commercetools.http.okhttp5; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.zip.GZIPOutputStream; + +import io.vrap.rmf.base.client.ApiHttpResponse; +import io.vrap.rmf.base.client.HttpClientSupplier; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import okhttp3.*; +import okio.Okio; + +public class SupplierTest { + @Test + public void testCreate() { + Assertions.assertThat(HttpClientSupplier.of().get()).isInstanceOf(CtOkHttp5Client.class); + } + + @Test + public void testUnzip() throws IOException { + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + GZIPOutputStream gzipOs = new GZIPOutputStream(os); + byte[] buffer = "Sample Text".getBytes(); + gzipOs.write(buffer, 0, buffer.length); + gzipOs.close(); + ByteArrayInputStream inputStream = new ByteArrayInputStream(os.toByteArray()); + + CtOkHttp5Client.UnzippingInterceptor interceptor = new CtOkHttp5Client.UnzippingInterceptor(); + + Response gzipped = new Response.Builder().request(new Request.Builder().url("http://localhost").build()) + .protocol(Protocol.HTTP_1_1) + .addHeader("content-encoding", "gzip") + .addHeader("content-type", "application/json") + .code(200) + .message("Ok") + .body(ResponseBody.create(MediaType.parse("application/json"), -1L, + Okio.buffer(Okio.source(inputStream)))) + .build(); + Assertions.assertThat(gzipped.body().source().isOpen()).isTrue(); + + Response unzipped = interceptor.unzip(gzipped); + + Assertions.assertThat(gzipped.body().source().isOpen()).isTrue(); + Assertions.assertThat(unzipped.body().source().isOpen()).isTrue(); + Assertions.assertThat(inputStream.available()).isEqualTo(31); + + ApiHttpResponse response = CtOkHttp5Client.toResponse(unzipped); + + Assertions.assertThat(gzipped.body().source().isOpen()).isFalse(); + Assertions.assertThat(unzipped.body().source().isOpen()).isFalse(); + Assertions.assertThat(inputStream.available()).isEqualTo(0); + + String text = new String(response.getBody(), StandardCharsets.UTF_8); + Assertions.assertThat(text).isEqualTo("Sample Text"); + } +} diff --git a/licenses/commercetools-okhttp-client5/index.json b/licenses/commercetools-okhttp-client5/index.json new file mode 100644 index 0000000000..012e3debbd --- /dev/null +++ b/licenses/commercetools-okhttp-client5/index.json @@ -0,0 +1,250 @@ +{ + "dependencies": [ + { + "moduleName": "com.fasterxml.jackson.core:jackson-annotations", + "moduleVersion": "2.19.1", + "moduleUrls": [ + "https://github.com/FasterXML/jackson" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "com.fasterxml.jackson.core:jackson-core", + "moduleVersion": "2.19.1", + "moduleUrls": [ + "https://github.com/FasterXML/jackson-core" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "com.fasterxml.jackson.core:jackson-databind", + "moduleVersion": "2.19.1", + "moduleUrls": [ + "https://github.com/FasterXML/jackson" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", + "moduleVersion": "2.19.1", + "moduleUrls": [ + "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "com.google.code.findbugs:jsr305", + "moduleVersion": "3.0.2", + "moduleUrls": [ + "http://findbugs.sourceforge.net/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "com.spotify:completable-futures", + "moduleVersion": "0.3.6", + "moduleUrls": [ + "https://spotify.github.io/completable-futures" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "com.squareup.okhttp3:okhttp", + "moduleVersion": "5.3.2" + }, + { + "moduleName": "com.squareup.okhttp3:okhttp-jvm", + "moduleVersion": "5.3.2", + "moduleUrls": [ + "https://square.github.io/okhttp/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "com.squareup.okio:okio", + "moduleVersion": "3.16.4" + }, + { + "moduleName": "com.squareup.okio:okio-jvm", + "moduleVersion": "3.16.4", + "moduleUrls": [ + "https://github.com/square/okio/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "dev.failsafe:failsafe", + "moduleVersion": "3.3.2", + "moduleLicenses": [ + { + "moduleLicense": null, + "moduleLicenseUrl": "http://apache.org/licenses/LICENSE-2.0" + }, + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "jakarta.validation:jakarta.validation-api", + "moduleVersion": "3.1.1", + "moduleUrls": [ + "https://beanvalidation.org", + "https://www.eclipse.org" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + }, + { + "moduleLicense": "Eclipse Public License - v 2.0", + "moduleLicenseUrl": "https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt" + }, + { + "moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception", + "moduleLicenseUrl": "https://openjdk.java.net/legal/gplv2+ce.html" + } + ] + }, + { + "moduleName": "org.apache.commons:commons-lang3", + "moduleVersion": "3.18.0", + "moduleUrls": [ + "https://commons.apache.org/proper/commons-lang/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "org.javassist:javassist", + "moduleVersion": "3.28.0-GA", + "moduleUrls": [ + "http://www.javassist.org/" + ], + "moduleLicenses": [ + { + "moduleLicense": null, + "moduleLicenseUrl": "http://www.mozilla.org/MPL/MPL-1.1.html, http://www.gnu.org/licenses/lgpl-2.1.html, http://www.apache.org/licenses/" + }, + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + }, + { + "moduleLicense": "GNU LESSER GENERAL PUBLIC LICENSE, Version 2.1", + "moduleLicenseUrl": "https://www.gnu.org/licenses/lgpl-2.1" + }, + { + "moduleLicense": "Mozilla Public License Version 1.1", + "moduleLicenseUrl": "https://www.mozilla.org/en-US/MPL/1.1" + } + ] + }, + { + "moduleName": "org.jetbrains.kotlin:kotlin-stdlib", + "moduleVersion": "2.2.21", + "moduleUrls": [ + "https://kotlinlang.org/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "org.jetbrains:annotations", + "moduleVersion": "13.0", + "moduleUrls": [ + "http://www.jetbrains.org" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, + { + "moduleName": "org.reflections:reflections", + "moduleVersion": "0.10.2", + "moduleUrls": [ + "http://github.com/ronmamo/reflections" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + }, + { + "moduleLicense": "WTFPL", + "moduleLicenseUrl": "http://www.wtfpl.net/" + } + ] + }, + { + "moduleName": "org.slf4j:slf4j-api", + "moduleVersion": "2.0.17", + "moduleUrls": [ + "http://www.slf4j.org" + ], + "moduleLicenses": [ + { + "moduleLicense": null, + "moduleLicenseUrl": "https://opensource.org/license/mit" + }, + { + "moduleLicense": "MIT License", + "moduleLicenseUrl": "https://opensource.org/licenses/MIT" + } + ] + } + ] +} \ No newline at end of file diff --git a/licenses/index.json b/licenses/index.json index 33210d5233..53382b3b92 100644 --- a/licenses/index.json +++ b/licenses/index.json @@ -451,10 +451,31 @@ } ] }, + { + "moduleName": "com.squareup.okhttp3:okhttp", + "moduleVersion": "5.3.2" + }, + { + "moduleName": "com.squareup.okhttp3:okhttp-jvm", + "moduleVersion": "5.3.2", + "moduleUrls": [ + "https://square.github.io/okhttp/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, { "moduleName": "com.squareup.okio:okio", "moduleVersion": "3.14.0" }, + { + "moduleName": "com.squareup.okio:okio", + "moduleVersion": "3.16.4" + }, { "moduleName": "com.squareup.okio:okio", "moduleVersion": "3.6.0" @@ -472,6 +493,19 @@ } ] }, + { + "moduleName": "com.squareup.okio:okio-jvm", + "moduleVersion": "3.16.4", + "moduleUrls": [ + "https://github.com/square/okio/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, { "moduleName": "com.squareup.okio:okio-jvm", "moduleVersion": "3.6.0", @@ -2029,6 +2063,19 @@ } ] }, + { + "moduleName": "org.jetbrains.kotlin:kotlin-stdlib", + "moduleVersion": "2.2.21", + "moduleUrls": [ + "https://kotlinlang.org/" + ], + "moduleLicenses": [ + { + "moduleLicense": "Apache License, Version 2.0", + "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" + } + ] + }, { "moduleName": "org.jetbrains.kotlin:kotlin-stdlib-common", "moduleVersion": "1.9.10", diff --git a/settings.gradle b/settings.gradle index f4643bbccb..a018e72001 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,6 +3,7 @@ includeBuild 'common-plugins' include 'rmf:rmf-java-base' include 'commercetools:commercetools-okhttp-client3' include 'commercetools:commercetools-okhttp-client4' +include 'commercetools:commercetools-okhttp-client5' include 'commercetools:commercetools-http-client' include 'commercetools:commercetools-javanet-client' include 'commercetools:commercetools-monitoring-newrelic'