diff --git a/docker-java-api/pom.xml b/docker-java-api/pom.xml
index f84228cac..f23df928c 100644
--- a/docker-java-api/pom.xml
+++ b/docker-java-api/pom.xml
@@ -55,64 +55,6 @@
-
-
-
- com.github.siom79.japicmp
- japicmp-maven-plugin
- 0.14.3
-
-
-
- com.github.docker-java
- docker-java
- 3.1.5
- jar
-
-
-
-
- ${project.build.directory}/${project.artifactId}-${project.version}.jar
-
-
-
- true
- public
- true
-
- com.github.dockerjava.api
-
-
-
- com.github.dockerjava.api.model.*$Serializer
- com.github.dockerjava.api.model.*$Deserializer
-
- com.github.dockerjava.api.command.DockerCmdExecFactory#init(com.github.dockerjava.core.DockerClientConfig)
- com.github.dockerjava.api.model.Identifier#tag
-
-
-
- METHOD_NEW_DEFAULT
- true
- true
-
-
- METHOD_ABSTRACT_NOW_DEFAULT
- true
- true
-
-
-
-
-
-
- verify
-
- cmp
-
-
-
-
diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/DelegatingDockerCmdExecFactory.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/DelegatingDockerCmdExecFactory.java
new file mode 100644
index 000000000..dbd691974
--- /dev/null
+++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/DelegatingDockerCmdExecFactory.java
@@ -0,0 +1,377 @@
+package com.github.dockerjava.api.command;
+
+import java.io.IOException;
+
+public class DelegatingDockerCmdExecFactory implements DockerCmdExecFactory {
+
+ // We're not using abstract class because we want
+ // the compiler to force us to implement new DockerCmdExecFactory when added
+ public DockerCmdExecFactory getDockerCmdExecFactory() {
+ throw new IllegalStateException("Implement me!");
+ }
+
+ @Override
+ public AuthCmd.Exec createAuthCmdExec() {
+ return getDockerCmdExecFactory().createAuthCmdExec();
+ }
+
+ @Override
+ public InfoCmd.Exec createInfoCmdExec() {
+ return getDockerCmdExecFactory().createInfoCmdExec();
+ }
+
+ @Override
+ public PingCmd.Exec createPingCmdExec() {
+ return getDockerCmdExecFactory().createPingCmdExec();
+ }
+
+ @Override
+ public ExecCreateCmd.Exec createExecCmdExec() {
+ return getDockerCmdExecFactory().createExecCmdExec();
+ }
+
+ @Override
+ public VersionCmd.Exec createVersionCmdExec() {
+ return getDockerCmdExecFactory().createVersionCmdExec();
+ }
+
+ @Override
+ public PullImageCmd.Exec createPullImageCmdExec() {
+ return getDockerCmdExecFactory().createPullImageCmdExec();
+ }
+
+ @Override
+ public PushImageCmd.Exec createPushImageCmdExec() {
+ return getDockerCmdExecFactory().createPushImageCmdExec();
+ }
+
+ @Override
+ public SaveImageCmd.Exec createSaveImageCmdExec() {
+ return getDockerCmdExecFactory().createSaveImageCmdExec();
+ }
+
+ @Override
+ public SaveImagesCmd.Exec createSaveImagesCmdExec() {
+ return getDockerCmdExecFactory().createSaveImagesCmdExec();
+ }
+
+ @Override
+ public CreateImageCmd.Exec createCreateImageCmdExec() {
+ return getDockerCmdExecFactory().createCreateImageCmdExec();
+ }
+
+ @Override
+ public LoadImageCmd.Exec createLoadImageCmdExec() {
+ return getDockerCmdExecFactory().createLoadImageCmdExec();
+ }
+
+ @Override
+ public SearchImagesCmd.Exec createSearchImagesCmdExec() {
+ return getDockerCmdExecFactory().createSearchImagesCmdExec();
+ }
+
+ @Override
+ public RemoveImageCmd.Exec createRemoveImageCmdExec() {
+ return getDockerCmdExecFactory().createRemoveImageCmdExec();
+ }
+
+ @Override
+ public ListImagesCmd.Exec createListImagesCmdExec() {
+ return getDockerCmdExecFactory().createListImagesCmdExec();
+ }
+
+ @Override
+ public InspectImageCmd.Exec createInspectImageCmdExec() {
+ return getDockerCmdExecFactory().createInspectImageCmdExec();
+ }
+
+ @Override
+ public ListContainersCmd.Exec createListContainersCmdExec() {
+ return getDockerCmdExecFactory().createListContainersCmdExec();
+ }
+
+ @Override
+ public CreateContainerCmd.Exec createCreateContainerCmdExec() {
+ return getDockerCmdExecFactory().createCreateContainerCmdExec();
+ }
+
+ @Override
+ public StartContainerCmd.Exec createStartContainerCmdExec() {
+ return getDockerCmdExecFactory().createStartContainerCmdExec();
+ }
+
+ @Override
+ public InspectContainerCmd.Exec createInspectContainerCmdExec() {
+ return getDockerCmdExecFactory().createInspectContainerCmdExec();
+ }
+
+ @Override
+ public RemoveContainerCmd.Exec createRemoveContainerCmdExec() {
+ return getDockerCmdExecFactory().createRemoveContainerCmdExec();
+ }
+
+ @Override
+ public WaitContainerCmd.Exec createWaitContainerCmdExec() {
+ return getDockerCmdExecFactory().createWaitContainerCmdExec();
+ }
+
+ @Override
+ public AttachContainerCmd.Exec createAttachContainerCmdExec() {
+ return getDockerCmdExecFactory().createAttachContainerCmdExec();
+ }
+
+ @Override
+ public ExecStartCmd.Exec createExecStartCmdExec() {
+ return getDockerCmdExecFactory().createExecStartCmdExec();
+ }
+
+ @Override
+ public InspectExecCmd.Exec createInspectExecCmdExec() {
+ return getDockerCmdExecFactory().createInspectExecCmdExec();
+ }
+
+ @Override
+ public LogContainerCmd.Exec createLogContainerCmdExec() {
+ return getDockerCmdExecFactory().createLogContainerCmdExec();
+ }
+
+ @Override
+ public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec() {
+ return getDockerCmdExecFactory().createCopyFileFromContainerCmdExec();
+ }
+
+ @Override
+ public CopyArchiveFromContainerCmd.Exec createCopyArchiveFromContainerCmdExec() {
+ return getDockerCmdExecFactory().createCopyArchiveFromContainerCmdExec();
+ }
+
+ @Override
+ public CopyArchiveToContainerCmd.Exec createCopyArchiveToContainerCmdExec() {
+ return getDockerCmdExecFactory().createCopyArchiveToContainerCmdExec();
+ }
+
+ @Override
+ public StopContainerCmd.Exec createStopContainerCmdExec() {
+ return getDockerCmdExecFactory().createStopContainerCmdExec();
+ }
+
+ @Override
+ public ContainerDiffCmd.Exec createContainerDiffCmdExec() {
+ return getDockerCmdExecFactory().createContainerDiffCmdExec();
+ }
+
+ @Override
+ public KillContainerCmd.Exec createKillContainerCmdExec() {
+ return getDockerCmdExecFactory().createKillContainerCmdExec();
+ }
+
+ @Override
+ public UpdateContainerCmd.Exec createUpdateContainerCmdExec() {
+ return getDockerCmdExecFactory().createUpdateContainerCmdExec();
+ }
+
+ @Override
+ public RenameContainerCmd.Exec createRenameContainerCmdExec() {
+ return getDockerCmdExecFactory().createRenameContainerCmdExec();
+ }
+
+ @Override
+ public RestartContainerCmd.Exec createRestartContainerCmdExec() {
+ return getDockerCmdExecFactory().createRestartContainerCmdExec();
+ }
+
+ @Override
+ public CommitCmd.Exec createCommitCmdExec() {
+ return getDockerCmdExecFactory().createCommitCmdExec();
+ }
+
+ @Override
+ public BuildImageCmd.Exec createBuildImageCmdExec() {
+ return getDockerCmdExecFactory().createBuildImageCmdExec();
+ }
+
+ @Override
+ public TopContainerCmd.Exec createTopContainerCmdExec() {
+ return getDockerCmdExecFactory().createTopContainerCmdExec();
+ }
+
+ @Override
+ public TagImageCmd.Exec createTagImageCmdExec() {
+ return getDockerCmdExecFactory().createTagImageCmdExec();
+ }
+
+ @Override
+ public PauseContainerCmd.Exec createPauseContainerCmdExec() {
+ return getDockerCmdExecFactory().createPauseContainerCmdExec();
+ }
+
+ @Override
+ public UnpauseContainerCmd.Exec createUnpauseContainerCmdExec() {
+ return getDockerCmdExecFactory().createUnpauseContainerCmdExec();
+ }
+
+ @Override
+ public EventsCmd.Exec createEventsCmdExec() {
+ return getDockerCmdExecFactory().createEventsCmdExec();
+ }
+
+ @Override
+ public StatsCmd.Exec createStatsCmdExec() {
+ return getDockerCmdExecFactory().createStatsCmdExec();
+ }
+
+ @Override
+ public CreateVolumeCmd.Exec createCreateVolumeCmdExec() {
+ return getDockerCmdExecFactory().createCreateVolumeCmdExec();
+ }
+
+ @Override
+ public InspectVolumeCmd.Exec createInspectVolumeCmdExec() {
+ return getDockerCmdExecFactory().createInspectVolumeCmdExec();
+ }
+
+ @Override
+ public RemoveVolumeCmd.Exec createRemoveVolumeCmdExec() {
+ return getDockerCmdExecFactory().createRemoveVolumeCmdExec();
+ }
+
+ @Override
+ public ListVolumesCmd.Exec createListVolumesCmdExec() {
+ return getDockerCmdExecFactory().createListVolumesCmdExec();
+ }
+
+ @Override
+ public ListNetworksCmd.Exec createListNetworksCmdExec() {
+ return getDockerCmdExecFactory().createListNetworksCmdExec();
+ }
+
+ @Override
+ public InspectNetworkCmd.Exec createInspectNetworkCmdExec() {
+ return getDockerCmdExecFactory().createInspectNetworkCmdExec();
+ }
+
+ @Override
+ public CreateNetworkCmd.Exec createCreateNetworkCmdExec() {
+ return getDockerCmdExecFactory().createCreateNetworkCmdExec();
+ }
+
+ @Override
+ public RemoveNetworkCmd.Exec createRemoveNetworkCmdExec() {
+ return getDockerCmdExecFactory().createRemoveNetworkCmdExec();
+ }
+
+ @Override
+ public ConnectToNetworkCmd.Exec createConnectToNetworkCmdExec() {
+ return getDockerCmdExecFactory().createConnectToNetworkCmdExec();
+ }
+
+ @Override
+ public DisconnectFromNetworkCmd.Exec createDisconnectFromNetworkCmdExec() {
+ return getDockerCmdExecFactory().createDisconnectFromNetworkCmdExec();
+ }
+
+ @Override
+ public InitializeSwarmCmd.Exec createInitializeSwarmCmdExec() {
+ return getDockerCmdExecFactory().createInitializeSwarmCmdExec();
+ }
+
+ @Override
+ public InspectSwarmCmd.Exec createInspectSwarmCmdExec() {
+ return getDockerCmdExecFactory().createInspectSwarmCmdExec();
+ }
+
+ @Override
+ public JoinSwarmCmd.Exec createJoinSwarmCmdExec() {
+ return getDockerCmdExecFactory().createJoinSwarmCmdExec();
+ }
+
+ @Override
+ public LeaveSwarmCmd.Exec createLeaveSwarmCmdExec() {
+ return getDockerCmdExecFactory().createLeaveSwarmCmdExec();
+ }
+
+ @Override
+ public UpdateSwarmCmd.Exec createUpdateSwarmCmdExec() {
+ return getDockerCmdExecFactory().createUpdateSwarmCmdExec();
+ }
+
+ @Override
+ public ListServicesCmd.Exec createListServicesCmdExec() {
+ return getDockerCmdExecFactory().createListServicesCmdExec();
+ }
+
+ @Override
+ public CreateServiceCmd.Exec createCreateServiceCmdExec() {
+ return getDockerCmdExecFactory().createCreateServiceCmdExec();
+ }
+
+ @Override
+ public InspectServiceCmd.Exec createInspectServiceCmdExec() {
+ return getDockerCmdExecFactory().createInspectServiceCmdExec();
+ }
+
+ @Override
+ public UpdateServiceCmd.Exec createUpdateServiceCmdExec() {
+ return getDockerCmdExecFactory().createUpdateServiceCmdExec();
+ }
+
+ @Override
+ public RemoveServiceCmd.Exec createRemoveServiceCmdExec() {
+ return getDockerCmdExecFactory().createRemoveServiceCmdExec();
+ }
+
+ @Override
+ public LogSwarmObjectCmd.Exec logSwarmObjectExec(String endpoint) {
+ return getDockerCmdExecFactory().logSwarmObjectExec(endpoint);
+ }
+
+ @Override
+ public ListSwarmNodesCmd.Exec listSwarmNodeCmdExec() {
+ return getDockerCmdExecFactory().listSwarmNodeCmdExec();
+ }
+
+ @Override
+ public InspectSwarmNodeCmd.Exec inspectSwarmNodeCmdExec() {
+ return getDockerCmdExecFactory().inspectSwarmNodeCmdExec();
+ }
+
+ @Override
+ public RemoveSwarmNodeCmd.Exec removeSwarmNodeCmdExec() {
+ return getDockerCmdExecFactory().removeSwarmNodeCmdExec();
+ }
+
+ @Override
+ public UpdateSwarmNodeCmd.Exec updateSwarmNodeCmdExec() {
+ return getDockerCmdExecFactory().updateSwarmNodeCmdExec();
+ }
+
+ @Override
+ public ListTasksCmd.Exec listTasksCmdExec() {
+ return getDockerCmdExecFactory().listTasksCmdExec();
+ }
+
+ @Override
+ public PruneCmd.Exec pruneCmdExec() {
+ return getDockerCmdExecFactory().pruneCmdExec();
+ }
+
+ @Override
+ public ListSecretsCmd.Exec createListSecretsCmdExec() {
+ return getDockerCmdExecFactory().createListSecretsCmdExec();
+ }
+
+ @Override
+ public CreateSecretCmd.Exec createCreateSecretCmdExec() {
+ return getDockerCmdExecFactory().createCreateSecretCmdExec();
+ }
+
+ @Override
+ public RemoveSecretCmd.Exec createRemoveSecretCmdExec() {
+ return getDockerCmdExecFactory().createRemoveSecretCmdExec();
+ }
+
+ @Override
+ public void close() throws IOException {
+ getDockerCmdExecFactory().close();
+ }
+}
diff --git a/docker-java-core/pom.xml b/docker-java-core/pom.xml
index 5238f816a..ed77c9db7 100644
--- a/docker-java-core/pom.xml
+++ b/docker-java-core/pom.xml
@@ -70,6 +70,13 @@
3.0.1u2
provided
+
+
+ org.immutables
+ value
+ 2.8.2
+ provided
+
diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerCmdExecFactory.java b/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerCmdExecFactory.java
new file mode 100644
index 000000000..5e13824ef
--- /dev/null
+++ b/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerCmdExecFactory.java
@@ -0,0 +1,154 @@
+package com.github.dockerjava.core;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.SetMultimap;
+import com.google.common.escape.Escaper;
+import com.google.common.net.UrlEscapers;
+import org.apache.commons.lang.StringUtils;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public final class DefaultDockerCmdExecFactory extends AbstractDockerCmdExecFactory {
+
+ private final DockerHttpClient dockerHttpClient;
+
+ private final ObjectMapper objectMapper;
+
+ public DefaultDockerCmdExecFactory(
+ DockerHttpClient dockerHttpClient,
+ ObjectMapper objectMapper
+ ) {
+ this.dockerHttpClient = dockerHttpClient;
+ this.objectMapper = objectMapper;
+ }
+
+ public DockerHttpClient getDockerHttpClient() {
+ return dockerHttpClient;
+ }
+
+ @Override
+ protected WebTarget getBaseResource() {
+ return new DefaultWebTarget();
+ }
+
+ @Override
+ public void close() throws IOException {
+ dockerHttpClient.close();
+ }
+
+ private class DefaultWebTarget implements WebTarget {
+
+ final ImmutableList path;
+
+ final SetMultimap queryParams;
+
+ DefaultWebTarget() {
+ this(
+ ImmutableList.of(),
+ MultimapBuilder.hashKeys().hashSetValues().build()
+ );
+ }
+
+ DefaultWebTarget(
+ ImmutableList path,
+ SetMultimap queryParams
+ ) {
+ this.path = path;
+ this.queryParams = queryParams;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("DefaultWebTarget{path=%s, queryParams=%s}", path, queryParams);
+ }
+
+ @Override
+ public InvocationBuilder request() {
+ String resource = StringUtils.join(path, "/");
+
+ if (!resource.startsWith("/")) {
+ resource = "/" + resource;
+ }
+
+ if (!queryParams.isEmpty()) {
+ Escaper urlFormParameterEscaper = UrlEscapers.urlFormParameterEscaper();
+ resource = queryParams.asMap().entrySet().stream()
+ .flatMap(entry -> {
+ return entry.getValue().stream().map(s -> {
+ return entry.getKey() + "=" + urlFormParameterEscaper.escape(s);
+ });
+ })
+ .collect(Collectors.joining("&", resource + "?", ""));
+ }
+
+ return new DefaultInvocationBuilder(
+ dockerHttpClient, objectMapper, resource
+ );
+ }
+
+ @Override
+ public DefaultWebTarget path(String... components) {
+ ImmutableList newPath = ImmutableList.builder()
+ .addAll(path)
+ .add(components)
+ .build();
+ return new DefaultWebTarget(newPath, queryParams);
+ }
+
+ @Override
+ public DefaultWebTarget resolveTemplate(String name, Object value) {
+ ImmutableList.Builder newPath = ImmutableList.builder();
+ for (String component : path) {
+ component = component.replaceAll(
+ "\\{" + name + "\\}",
+ UrlEscapers.urlPathSegmentEscaper().escape(value.toString())
+ );
+ newPath.add(component);
+ }
+
+ return new DefaultWebTarget(newPath.build(), queryParams);
+ }
+
+ @Override
+ public DefaultWebTarget queryParam(String name, Object value) {
+ if (value == null) {
+ return this;
+ }
+
+ SetMultimap newQueryParams = HashMultimap.create(queryParams);
+ newQueryParams.put(name, value.toString());
+
+ return new DefaultWebTarget(path, newQueryParams);
+ }
+
+ @Override
+ public DefaultWebTarget queryParamsSet(String name, Set> values) {
+ SetMultimap newQueryParams = HashMultimap.create(queryParams);
+ newQueryParams.replaceValues(name, values.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.toSet()));
+
+ return new DefaultWebTarget(path, newQueryParams);
+ }
+
+ @Override
+ public DefaultWebTarget queryParamsJsonMap(String name, Map values) {
+ if (values == null || values.isEmpty()) {
+ return this;
+ }
+
+ // when param value is JSON string
+ try {
+ return queryParam(name, objectMapper.writeValueAsString(values));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultInvocationBuilder.java b/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultInvocationBuilder.java
new file mode 100644
index 000000000..50bd4612b
--- /dev/null
+++ b/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultInvocationBuilder.java
@@ -0,0 +1,296 @@
+package com.github.dockerjava.core;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.MappingIterator;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.exception.BadRequestException;
+import com.github.dockerjava.api.exception.ConflictException;
+import com.github.dockerjava.api.exception.DockerException;
+import com.github.dockerjava.api.exception.InternalServerErrorException;
+import com.github.dockerjava.api.exception.NotAcceptableException;
+import com.github.dockerjava.api.exception.NotFoundException;
+import com.github.dockerjava.api.exception.NotModifiedException;
+import com.github.dockerjava.api.exception.UnauthorizedException;
+import com.github.dockerjava.api.model.Frame;
+import org.apache.commons.io.IOUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+class DefaultInvocationBuilder implements InvocationBuilder {
+
+ private final DockerHttpClient.Request.Builder requestBuilder;
+ private final DockerHttpClient dockerHttpClient;
+ private final ObjectMapper objectMapper;
+
+ DefaultInvocationBuilder(DockerHttpClient dockerHttpClient, ObjectMapper objectMapper, String path) {
+ this.requestBuilder = DockerHttpClient.Request.builder().path(path);
+ this.dockerHttpClient = dockerHttpClient;
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public DefaultInvocationBuilder accept(MediaType mediaType) {
+ return header("accept", mediaType.getMediaType());
+ }
+
+ @Override
+ public DefaultInvocationBuilder header(String name, String value) {
+ requestBuilder.putHeader(name, value);
+ return this;
+ }
+
+ @Override
+ public void delete() {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.DELETE)
+ .build();
+
+ execute(request).close();
+ }
+
+ @Override
+ public void get(ResultCallback resultCallback) {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.GET)
+ .build();
+
+ executeAndStream(
+ request,
+ resultCallback,
+ new FramedInputStreamConsumer(resultCallback)
+ );
+ }
+
+ @Override
+ public T get(TypeReference typeReference) {
+ try (InputStream inputStream = get()) {
+ return objectMapper.readValue(inputStream, typeReference);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void get(TypeReference typeReference, ResultCallback resultCallback) {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.GET)
+ .build();
+
+ executeAndStream(
+ request,
+ resultCallback,
+ new JsonSink<>(typeReference, resultCallback)
+ );
+ }
+
+ @Override
+ public InputStream post(Object entity) {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.POST)
+ .putHeader("content-type", "application/json")
+ .body(encode(entity))
+ .build();
+
+ return execute(request).getBody();
+ }
+
+ @Override
+ public T post(Object entity, TypeReference typeReference) {
+ try {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.POST)
+ .putHeader("content-type", "application/json")
+ .body(new ByteArrayInputStream(objectMapper.writeValueAsBytes(entity)))
+ .build();
+
+ try (DockerHttpClient.Response response = execute(request)) {
+ return objectMapper.readValue(response.getBody(), typeReference);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void post(Object entity, TypeReference typeReference, ResultCallback resultCallback) {
+ try {
+ post(typeReference, resultCallback, new ByteArrayInputStream(objectMapper.writeValueAsBytes(entity)));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public T post(TypeReference typeReference, InputStream body) {
+ try (InputStream inputStream = post(body)) {
+ return objectMapper.readValue(inputStream, typeReference);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void post(Object entity, InputStream stdin, ResultCallback resultCallback) {
+ final DockerHttpClient.Request request;
+ try {
+ request = requestBuilder
+ .method(DockerHttpClient.Request.Method.POST)
+ .putHeader("content-type", "application/json")
+ .body(new ByteArrayInputStream(objectMapper.writeValueAsBytes(entity)))
+ .hijackedInput(stdin)
+ .build();
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+
+ executeAndStream(
+ request,
+ resultCallback,
+ new FramedInputStreamConsumer(resultCallback)
+ );
+ }
+
+ @Override
+ public void post(TypeReference typeReference, ResultCallback resultCallback, InputStream body) {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.POST)
+ .body(body)
+ .build();
+
+ executeAndStream(
+ request,
+ resultCallback,
+ new JsonSink<>(typeReference, resultCallback)
+ );
+ }
+
+ @Override
+ public void postStream(InputStream body) {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.POST)
+ .body(body)
+ .build();
+
+ execute(request).close();
+ }
+
+ @Override
+ public InputStream get() {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.GET)
+ .build();
+
+ return execute(request).getBody();
+ }
+
+ @Override
+ public void put(InputStream body, MediaType mediaType) {
+ DockerHttpClient.Request request = requestBuilder
+ .method(DockerHttpClient.Request.Method.PUT)
+ .putHeader("content-type", mediaType.toString())
+ .body(body)
+ .build();
+
+ execute(request).close();
+ }
+
+ protected DockerHttpClient.Response execute(DockerHttpClient.Request request) {
+ try {
+ DockerHttpClient.Response response = dockerHttpClient.execute(request);
+ int statusCode = response.getStatusCode();
+ if (statusCode < 200 || statusCode > 299) {
+ try {
+ String body = IOUtils.toString(response.getBody(), StandardCharsets.UTF_8);
+ switch (statusCode) {
+ case 304:
+ throw new NotModifiedException(body);
+ case 400:
+ throw new BadRequestException(body);
+ case 401:
+ throw new UnauthorizedException(body);
+ case 404:
+ throw new NotFoundException(body);
+ case 406:
+ throw new NotAcceptableException(body);
+ case 409:
+ throw new ConflictException(body);
+ case 500:
+ throw new InternalServerErrorException(body);
+ default:
+ throw new DockerException(body, statusCode);
+ }
+ } finally {
+ response.close();
+ }
+ } else {
+ return response;
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void executeAndStream(
+ DockerHttpClient.Request request,
+ ResultCallback callback,
+ Consumer sourceConsumer
+ ) {
+ Thread thread = new Thread(() -> {
+ try (DockerHttpClient.Response response = execute(request)) {
+ callback.onStart(response);
+
+ sourceConsumer.accept(response);
+ callback.onComplete();
+ } catch (Exception e) {
+ callback.onError(e);
+ }
+ }, "docker-java-stream-" + Objects.hashCode(request));
+ thread.setDaemon(true);
+
+ thread.start();
+ }
+
+ private InputStream encode(Object entity) {
+ if (entity == null) {
+ return null;
+ }
+
+ try {
+ return new ByteArrayInputStream(objectMapper.writeValueAsBytes(entity));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private class JsonSink implements Consumer {
+
+ private final TypeReference typeReference;
+
+ private final ResultCallback resultCallback;
+
+ JsonSink(TypeReference typeReference, ResultCallback resultCallback) {
+ this.typeReference = typeReference;
+ this.resultCallback = resultCallback;
+ }
+
+ @Override
+ public void accept(DockerHttpClient.Response response) {
+ try {
+ InputStream body = response.getBody();
+ MappingIterator