Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public String getDockerConfigPath() {
public DockerConfigFile getDockerConfig() {
if (dockerConfig == null) {
try {
dockerConfig = DockerConfigFile.loadConfig(getDockerConfigPath());
dockerConfig = DockerConfigFile.loadConfig(getObjectMapper(), getDockerConfigPath());
} catch (IOException e) {
throw new DockerClientException("Failed to parse docker configuration file", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import java.net.URI;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.dockerjava.api.model.AuthConfig;
import com.github.dockerjava.api.model.AuthConfigurations;

Expand Down Expand Up @@ -37,4 +39,20 @@ public interface DockerClientConfig {
*/
SSLConfig getSSLConfig();

default ObjectMapper getObjectMapper() {
return DefaultObjectMapperHolder.INSTANCE.getObjectMapper();
}
}

enum DefaultObjectMapperHolder {
INSTANCE;

private final ObjectMapper objectMapper = new ObjectMapper()
// TODO .setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL)
// TODO .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

public ObjectMapper getObjectMapper() {
return objectMapper;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.github.dockerjava.core;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -20,12 +19,10 @@
import java.util.List;
import java.util.Map;

@JsonIgnoreProperties(ignoreUnknown = true)
public class DockerConfigFile {
private static final String DOCKER_LEGACY_CFG = ".dockercfg";
private static final String DOCKER_CFG = "config.json";

private static final ObjectMapper MAPPER = new ObjectMapper();
private static final TypeReference<Map<String, AuthConfig>> CONFIG_MAP_TYPE = new TypeReference<Map<String, AuthConfig>>() {
};

Expand Down Expand Up @@ -118,18 +115,24 @@ public String toString() {
}

@Nonnull
@Deprecated
public static DockerConfigFile loadConfig(@CheckForNull String dockerConfigPath) throws IOException {
return loadConfig(DefaultObjectMapperHolder.INSTANCE.getObjectMapper(), dockerConfigPath);
}

@Nonnull
public static DockerConfigFile loadConfig(ObjectMapper objectMapper, @CheckForNull String dockerConfigPath) throws IOException {
// no any configs, but for empty auths return non null object
if (dockerConfigPath == null) {
return new DockerConfigFile();
}

//parse new docker config file format
DockerConfigFile dockerConfig = loadCurrentConfig(dockerConfigPath);
DockerConfigFile dockerConfig = loadCurrentConfig(objectMapper, dockerConfigPath);

//parse old auth config file format
if (dockerConfig == null) {
dockerConfig = loadLegacyConfig(dockerConfigPath);
dockerConfig = loadLegacyConfig(objectMapper, dockerConfigPath);
}

//otherwise create default config
Expand All @@ -148,22 +151,22 @@ public static DockerConfigFile loadConfig(@CheckForNull String dockerConfigPath)
}

@CheckForNull
private static DockerConfigFile loadCurrentConfig(@CheckForNull String dockerConfigPath) throws IOException {
private static DockerConfigFile loadCurrentConfig(ObjectMapper objectMapper, @CheckForNull String dockerConfigPath) throws IOException {
File dockerCfgFile = new File(dockerConfigPath, DOCKER_CFG);

if (!dockerCfgFile.exists() || !dockerCfgFile.isFile()) {
return null;
}

try {
return MAPPER.readValue(dockerCfgFile, DockerConfigFile.class);
return objectMapper.readValue(dockerCfgFile, DockerConfigFile.class);
} catch (IOException e) {
throw new IOException("Failed to parse docker " + DOCKER_CFG, e);
}
}

@CheckForNull
private static DockerConfigFile loadLegacyConfig(String dockerConfigPath) throws IOException {
private static DockerConfigFile loadLegacyConfig(ObjectMapper objectMapper, String dockerConfigPath) throws IOException {
File dockerLegacyCfgFile = new File(dockerConfigPath, DOCKER_LEGACY_CFG);

if (!dockerLegacyCfgFile.exists() || !dockerLegacyCfgFile.isFile()) {
Expand All @@ -172,7 +175,7 @@ private static DockerConfigFile loadLegacyConfig(String dockerConfigPath) throws

//parse legacy auth config file format
try {
return new DockerConfigFile(MAPPER.<Map<String, AuthConfig>>readValue(dockerLegacyCfgFile, CONFIG_MAP_TYPE));
return new DockerConfigFile(objectMapper.<Map<String, AuthConfig>>readValue(dockerLegacyCfgFile, CONFIG_MAP_TYPE));
} catch (IOException e) {
// pass
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.dockerjava.api.async.ResultCallback;
Expand All @@ -22,30 +23,38 @@ public class JsonStreamProcessor<T> implements ResponseStreamProcessor<T> {

private static final JsonFactory JSON_FACTORY = new JsonFactory();

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

private final Class<T> clazz;

private final ObjectMapper objectMapper;

@Deprecated
public JsonStreamProcessor(Class<T> clazz) {
this(
new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES),
clazz
);
}

public JsonStreamProcessor(ObjectMapper objectMapper, Class<T> clazz) {
this.clazz = clazz;
this.objectMapper = objectMapper.copy().enable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
}

@Override
public void processResponseStream(InputStream response, ResultCallback<T> resultCallback) {

resultCallback.onStart(response);
OBJECT_MAPPER.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);

try {
JsonParser jp = JSON_FACTORY.createParser(response);
Boolean closed = jp.isClosed();
JsonToken nextToken = jp.nextToken();
while (!closed && nextToken != null && nextToken != JsonToken.END_OBJECT) {
try {
ObjectNode objectNode = OBJECT_MAPPER.readTree(jp);
ObjectNode objectNode = objectMapper.readTree(jp);
// exclude empty item serialization into class #461
if (!objectNode.isEmpty(null)) {
T next = OBJECT_MAPPER.treeToValue(objectNode, clazz);
T next = objectMapper.treeToValue(objectNode, clazz);
resultCallback.onNext(next);
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SIMPLE_STYLE);
}

@Deprecated
protected String registryAuth(AuthConfig authConfig) {
try {
return Base64.getEncoder().encodeToString(new ObjectMapper().writeValueAsBytes(authConfig));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected AuthConfigurations getBuildAuthConfigs() {

protected String registryAuth(@Nonnull AuthConfig authConfig) {
try {
return BaseEncoding.base64Url().encode(new ObjectMapper().writeValueAsString(authConfig).getBytes());
return BaseEncoding.base64Url().encode(dockerClientConfig.getObjectMapper().writeValueAsString(authConfig).getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand All @@ -52,8 +52,8 @@ protected String registryAuth(@Nonnull AuthConfig authConfig) {
protected String registryConfigs(@Nonnull AuthConfigurations authConfigs) {
try {
final String json;
final ObjectMapper objectMapper = new ObjectMapper();
final RemoteApiVersion apiVersion = dockerClientConfig.getApiVersion();
ObjectMapper objectMapper = dockerClientConfig.getObjectMapper();

if (apiVersion.equals(UNKNOWN_VERSION)) {
ObjectNode rootNode = objectMapper.valueToTree(authConfigs.getConfigs()); // all registries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class CacheFromEncoder {
private CacheFromEncoder() {
}

// This instance MUST NOT be used for domain-specific serialization of the docker-java types
private static final ObjectMapper MAPPER = new ObjectMapper();

public static String jsonEncode(Collection<String> imageIds) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class FiltersEncoder {
private FiltersEncoder() {
}

// This instance MUST NOT be used for domain-specific serialization of the docker-java types
private static final ObjectMapper MAPPER = new ObjectMapper();

public static String jsonEncode(Map<String, List<String>> mapStringListString) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ public abstract class AbstrDockerCmdExec {

private final WebTarget baseResource;

protected final ObjectMapper objectMapper;

public AbstrDockerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) {
checkNotNull(baseResource, "baseResource was not specified");
checkNotNull(dockerClientConfig, "dockerClientConfig was not specified");
this.baseResource = baseResource;
this.dockerClientConfig = dockerClientConfig;
this.objectMapper = dockerClientConfig.getObjectMapper();
checkNotNull(objectMapper, "objectMapper was not specified");
}

protected WebTarget getBaseResource() {
Expand All @@ -39,7 +43,7 @@ protected AuthConfigurations getBuildAuthConfigs() {

protected String registryAuth(AuthConfig authConfig) {
try {
return BaseEncoding.base64Url().encode(new ObjectMapper().writeValueAsString(authConfig).getBytes());
return BaseEncoding.base64Url().encode(objectMapper.writeValueAsString(authConfig).getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand All @@ -60,7 +64,6 @@ protected Invocation.Builder resourceWithOptionalAuthConfig(AuthConfig authConfi
protected String registryConfigs(AuthConfigurations authConfigs) {
try {
final String json;
final ObjectMapper objectMapper = new ObjectMapper();
final RemoteApiVersion apiVersion = dockerClientConfig.getApiVersion();

if (apiVersion.equals(UNKNOWN_VERSION)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.github.dockerjava.core.util.CacheFromEncoder;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.RequestEntityProcessing;
Expand All @@ -32,8 +30,6 @@ public class BuildImageCmdExec extends AbstrAsyncDockerCmdExec<BuildImageCmd, Bu
BuildImageCmd.Exec {
private static final Logger LOGGER = LoggerFactory.getLogger(BuildImageCmdExec.class);

private static final ObjectMapper MAPPER = new ObjectMapper();

public BuildImageCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) {
super(baseResource, dockerClientConfig);
}
Expand Down Expand Up @@ -137,7 +133,7 @@ protected AbstractCallbackNotifier<BuildResponseItem> callbackNotifier(BuildImag

LOGGER.trace("POST: {}", webTarget);

return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(BuildResponseItem.class),
return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(objectMapper, BuildResponseItem.class),
resultCallback,
resourceWithOptionalAuthConfig(command, webTarget.request()).accept(MediaType.TEXT_PLAIN),
entity(command.getTarInputStream(), "application/tar")
Expand All @@ -148,7 +144,7 @@ private WebTarget writeMap(WebTarget webTarget, String name, Map<String, String>
if (value != null && !value.isEmpty()) {
try {
return webTarget.queryParam(name,
URLEncoder.encode(MAPPER.writeValueAsString(value), "UTF-8").replaceAll("\\+", "%20"));
URLEncoder.encode(objectMapper.writeValueAsString(value), "UTF-8").replaceAll("\\+", "%20"));
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ protected AbstractCallbackNotifier<Event> callbackNotifier(EventsCmd command, Re

LOGGER.trace("GET: {}", webTarget);

return new GETCallbackNotifier<>(new JsonStreamProcessor<>(Event.class), resultCallback,
return new GETCallbackNotifier<>(new JsonStreamProcessor<>(objectMapper, Event.class), resultCallback,
webTarget.request());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.github.dockerjava.jaxrs;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.github.dockerjava.api.command.AttachContainerCmd;
import com.github.dockerjava.api.command.AuthCmd;
Expand Down Expand Up @@ -157,13 +155,12 @@ public void init(DockerClientConfig dockerClientConfig) {
if (requestEntityProcessing != null) {
clientConfig.property(ClientProperties.REQUEST_ENTITY_PROCESSING, requestEntityProcessing);
}
clientConfig.register(ResponseStatusExceptionFilter.class);

clientConfig.register(new ResponseStatusExceptionFilter(dockerClientConfig.getObjectMapper()));
clientConfig.register(JsonClientFilter.class);
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
clientConfig.register(new JacksonJsonProvider(objectMapper));
clientConfig.register(new JacksonJsonProvider(dockerClientConfig.getObjectMapper()));

// logging may disabled via log level
clientConfig.register(new SelectiveLoggingFilter(LOGGER, true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ protected AbstractCallbackNotifier<PullResponseItem> callbackNotifier(PullImageC
Builder builder = resourceWithOptionalAuthConfig(command.getAuthConfig(), webResource.request()).accept(
MediaType.APPLICATION_OCTET_STREAM_TYPE);

return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(
PullResponseItem.class), resultCallback, builder, entity(null, MediaType.APPLICATION_JSON));
return new POSTCallbackNotifier<>(
new JsonStreamProcessor<>(objectMapper, PullResponseItem.class),
resultCallback, builder, entity(null, MediaType.APPLICATION_JSON));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ protected AbstractCallbackNotifier<PushResponseItem> callbackNotifier(PushImageC
Builder builder = resourceWithAuthConfig(command.getAuthConfig(), webResource.request())
.accept(MediaType.APPLICATION_JSON);

return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(
PushResponseItem.class), resultCallback, builder, entity(null, MediaType.APPLICATION_JSON));
return new POSTCallbackNotifier<>(
new JsonStreamProcessor<>(objectMapper, PushResponseItem.class),
resultCallback, builder, entity(null, MediaType.APPLICATION_JSON));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected AbstractCallbackNotifier<Statistics> callbackNotifier(StatsCmd command

LOGGER.trace("GET: {}", webTarget);

return new GETCallbackNotifier<>(new JsonStreamProcessor<>(Statistics.class),
return new GETCallbackNotifier<>(new JsonStreamProcessor<>(objectMapper, Statistics.class),
resultCallback, webTarget.request());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected AbstractCallbackNotifier<WaitResponse> callbackNotifier(WaitContainerC

LOGGER.trace("POST: {}", webResource);

return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(WaitResponse.class),
return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(objectMapper, WaitResponse.class),
resultCallback, webResource.request().accept(MediaType.APPLICATION_JSON), entity(null,
MediaType.APPLICATION_JSON));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.core.MediaType;

import com.fasterxml.jackson.databind.DeserializationFeature;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -35,6 +36,17 @@ public class ResponseStatusExceptionFilter implements ClientResponseFilter {

private static final Logger LOG = LoggerFactory.getLogger(ResponseStatusExceptionFilter.class);

private final ObjectMapper objectMapper;

@Deprecated
public ResponseStatusExceptionFilter() {
this(new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
}

public ResponseStatusExceptionFilter(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}

@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
int status = responseContext.getStatus();
Expand Down Expand Up @@ -84,7 +96,7 @@ private String getBodyAsMessage(ClientResponseContext responseContext) {

if (MediaType.APPLICATION_JSON_TYPE.equals(mediaType)) {
try {
JsonNode node = new ObjectMapper().readTree(message);
JsonNode node = objectMapper.readTree(message);
if (node != null) {
JsonNode messageNode = node.get("message");
if (messageNode != null && messageNode.isTextual()) {
Expand Down
Loading