Skip to content

Commit 41eea38

Browse files
authored
Replace static ObjectMappers with DockerClientConfig#getObjectMapper (#1275)
* Replace static ObjectMappers with DockerClientConfig#getObjectMapper * remove unused `ObjectMapper` field * revert change * simplify AbstrDockerCmdExec
1 parent 18ad695 commit 41eea38

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+248
-171
lines changed

docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ public String getDockerConfigPath() {
242242
public DockerConfigFile getDockerConfig() {
243243
if (dockerConfig == null) {
244244
try {
245-
dockerConfig = DockerConfigFile.loadConfig(getDockerConfigPath());
245+
dockerConfig = DockerConfigFile.loadConfig(getObjectMapper(), getDockerConfigPath());
246246
} catch (IOException e) {
247247
throw new DockerClientException("Failed to parse docker configuration file", e);
248248
}

docker-java-core/src/main/java/com/github/dockerjava/core/DockerClientConfig.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import java.net.URI;
77

8+
import com.fasterxml.jackson.databind.DeserializationFeature;
9+
import com.fasterxml.jackson.databind.ObjectMapper;
810
import com.github.dockerjava.api.model.AuthConfig;
911
import com.github.dockerjava.api.model.AuthConfigurations;
1012

@@ -37,4 +39,20 @@ public interface DockerClientConfig {
3739
*/
3840
SSLConfig getSSLConfig();
3941

42+
default ObjectMapper getObjectMapper() {
43+
return DefaultObjectMapperHolder.INSTANCE.getObjectMapper();
44+
}
45+
}
46+
47+
enum DefaultObjectMapperHolder {
48+
INSTANCE;
49+
50+
private final ObjectMapper objectMapper = new ObjectMapper()
51+
// TODO .setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL)
52+
// TODO .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
53+
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
54+
55+
public ObjectMapper getObjectMapper() {
56+
return objectMapper;
57+
}
4058
}

docker-java-core/src/main/java/com/github/dockerjava/core/DockerConfigFile.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.github.dockerjava.core;
22

3-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
43
import com.fasterxml.jackson.annotation.JsonProperty;
54
import com.fasterxml.jackson.core.type.TypeReference;
65
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -20,12 +19,10 @@
2019
import java.util.List;
2120
import java.util.Map;
2221

23-
@JsonIgnoreProperties(ignoreUnknown = true)
2422
public class DockerConfigFile {
2523
private static final String DOCKER_LEGACY_CFG = ".dockercfg";
2624
private static final String DOCKER_CFG = "config.json";
2725

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

@@ -118,18 +115,24 @@ public String toString() {
118115
}
119116

120117
@Nonnull
118+
@Deprecated
121119
public static DockerConfigFile loadConfig(@CheckForNull String dockerConfigPath) throws IOException {
120+
return loadConfig(DefaultObjectMapperHolder.INSTANCE.getObjectMapper(), dockerConfigPath);
121+
}
122+
123+
@Nonnull
124+
public static DockerConfigFile loadConfig(ObjectMapper objectMapper, @CheckForNull String dockerConfigPath) throws IOException {
122125
// no any configs, but for empty auths return non null object
123126
if (dockerConfigPath == null) {
124127
return new DockerConfigFile();
125128
}
126129

127130
//parse new docker config file format
128-
DockerConfigFile dockerConfig = loadCurrentConfig(dockerConfigPath);
131+
DockerConfigFile dockerConfig = loadCurrentConfig(objectMapper, dockerConfigPath);
129132

130133
//parse old auth config file format
131134
if (dockerConfig == null) {
132-
dockerConfig = loadLegacyConfig(dockerConfigPath);
135+
dockerConfig = loadLegacyConfig(objectMapper, dockerConfigPath);
133136
}
134137

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

150153
@CheckForNull
151-
private static DockerConfigFile loadCurrentConfig(@CheckForNull String dockerConfigPath) throws IOException {
154+
private static DockerConfigFile loadCurrentConfig(ObjectMapper objectMapper, @CheckForNull String dockerConfigPath) throws IOException {
152155
File dockerCfgFile = new File(dockerConfigPath, DOCKER_CFG);
153156

154157
if (!dockerCfgFile.exists() || !dockerCfgFile.isFile()) {
155158
return null;
156159
}
157160

158161
try {
159-
return MAPPER.readValue(dockerCfgFile, DockerConfigFile.class);
162+
return objectMapper.readValue(dockerCfgFile, DockerConfigFile.class);
160163
} catch (IOException e) {
161164
throw new IOException("Failed to parse docker " + DOCKER_CFG, e);
162165
}
163166
}
164167

165168
@CheckForNull
166-
private static DockerConfigFile loadLegacyConfig(String dockerConfigPath) throws IOException {
169+
private static DockerConfigFile loadLegacyConfig(ObjectMapper objectMapper, String dockerConfigPath) throws IOException {
167170
File dockerLegacyCfgFile = new File(dockerConfigPath, DOCKER_LEGACY_CFG);
168171

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

173176
//parse legacy auth config file format
174177
try {
175-
return new DockerConfigFile(MAPPER.<Map<String, AuthConfig>>readValue(dockerLegacyCfgFile, CONFIG_MAP_TYPE));
178+
return new DockerConfigFile(objectMapper.<Map<String, AuthConfig>>readValue(dockerLegacyCfgFile, CONFIG_MAP_TYPE));
176179
} catch (IOException e) {
177180
// pass
178181
}

docker-java-core/src/main/java/com/github/dockerjava/core/async/JsonStreamProcessor.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.fasterxml.jackson.core.JsonFactory;
1010
import com.fasterxml.jackson.core.JsonParser;
1111
import com.fasterxml.jackson.core.JsonToken;
12+
import com.fasterxml.jackson.databind.DeserializationFeature;
1213
import com.fasterxml.jackson.databind.ObjectMapper;
1314
import com.fasterxml.jackson.databind.node.ObjectNode;
1415
import com.github.dockerjava.api.async.ResultCallback;
@@ -22,30 +23,38 @@ public class JsonStreamProcessor<T> implements ResponseStreamProcessor<T> {
2223

2324
private static final JsonFactory JSON_FACTORY = new JsonFactory();
2425

25-
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
26-
2726
private final Class<T> clazz;
2827

28+
private final ObjectMapper objectMapper;
29+
30+
@Deprecated
2931
public JsonStreamProcessor(Class<T> clazz) {
32+
this(
33+
new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES),
34+
clazz
35+
);
36+
}
37+
38+
public JsonStreamProcessor(ObjectMapper objectMapper, Class<T> clazz) {
3039
this.clazz = clazz;
40+
this.objectMapper = objectMapper.copy().enable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
3141
}
3242

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

3646
resultCallback.onStart(response);
37-
OBJECT_MAPPER.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
3847

3948
try {
4049
JsonParser jp = JSON_FACTORY.createParser(response);
4150
Boolean closed = jp.isClosed();
4251
JsonToken nextToken = jp.nextToken();
4352
while (!closed && nextToken != null && nextToken != JsonToken.END_OBJECT) {
4453
try {
45-
ObjectNode objectNode = OBJECT_MAPPER.readTree(jp);
54+
ObjectNode objectNode = objectMapper.readTree(jp);
4655
// exclude empty item serialization into class #461
4756
if (!objectNode.isEmpty(null)) {
48-
T next = OBJECT_MAPPER.treeToValue(objectNode, clazz);
57+
T next = objectMapper.treeToValue(objectNode, clazz);
4958
resultCallback.onNext(next);
5059
}
5160
} catch (Exception e) {

docker-java-core/src/main/java/com/github/dockerjava/core/command/AbstrDockerCmd.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public String toString() {
4444
return ReflectionToStringBuilder.toString(this, ToStringStyle.SIMPLE_STYLE);
4545
}
4646

47+
@Deprecated
4748
protected String registryAuth(AuthConfig authConfig) {
4849
try {
4950
return Base64.getEncoder().encodeToString(new ObjectMapper().writeValueAsBytes(authConfig));

docker-java-core/src/main/java/com/github/dockerjava/core/exec/AbstrDockerCmdExec.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ protected AuthConfigurations getBuildAuthConfigs() {
4242

4343
protected String registryAuth(@Nonnull AuthConfig authConfig) {
4444
try {
45-
return BaseEncoding.base64Url().encode(new ObjectMapper().writeValueAsString(authConfig).getBytes());
45+
return BaseEncoding.base64Url().encode(dockerClientConfig.getObjectMapper().writeValueAsString(authConfig).getBytes());
4646
} catch (IOException e) {
4747
throw new RuntimeException(e);
4848
}
@@ -52,8 +52,8 @@ protected String registryAuth(@Nonnull AuthConfig authConfig) {
5252
protected String registryConfigs(@Nonnull AuthConfigurations authConfigs) {
5353
try {
5454
final String json;
55-
final ObjectMapper objectMapper = new ObjectMapper();
5655
final RemoteApiVersion apiVersion = dockerClientConfig.getApiVersion();
56+
ObjectMapper objectMapper = dockerClientConfig.getObjectMapper();
5757

5858
if (apiVersion.equals(UNKNOWN_VERSION)) {
5959
ObjectNode rootNode = objectMapper.valueToTree(authConfigs.getConfigs()); // all registries

docker-java-core/src/main/java/com/github/dockerjava/core/util/CacheFromEncoder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class CacheFromEncoder {
1313
private CacheFromEncoder() {
1414
}
1515

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

1819
public static String jsonEncode(Collection<String> imageIds) {

docker-java-core/src/main/java/com/github/dockerjava/core/util/FiltersEncoder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class FiltersEncoder {
1616
private FiltersEncoder() {
1717
}
1818

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

2122
public static String jsonEncode(Map<String, List<String>> mapStringListString) {

docker-java-transport-jersey/src/main/java/com/github/dockerjava/jaxrs/AbstrDockerCmdExec.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ public abstract class AbstrDockerCmdExec {
2222

2323
private final WebTarget baseResource;
2424

25+
protected final ObjectMapper objectMapper;
26+
2527
public AbstrDockerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) {
2628
checkNotNull(baseResource, "baseResource was not specified");
2729
checkNotNull(dockerClientConfig, "dockerClientConfig was not specified");
2830
this.baseResource = baseResource;
2931
this.dockerClientConfig = dockerClientConfig;
32+
this.objectMapper = dockerClientConfig.getObjectMapper();
33+
checkNotNull(objectMapper, "objectMapper was not specified");
3034
}
3135

3236
protected WebTarget getBaseResource() {
@@ -39,7 +43,7 @@ protected AuthConfigurations getBuildAuthConfigs() {
3943

4044
protected String registryAuth(AuthConfig authConfig) {
4145
try {
42-
return BaseEncoding.base64Url().encode(new ObjectMapper().writeValueAsString(authConfig).getBytes());
46+
return BaseEncoding.base64Url().encode(objectMapper.writeValueAsString(authConfig).getBytes());
4347
} catch (IOException e) {
4448
throw new RuntimeException(e);
4549
}
@@ -60,7 +64,6 @@ protected Invocation.Builder resourceWithOptionalAuthConfig(AuthConfig authConfi
6064
protected String registryConfigs(AuthConfigurations authConfigs) {
6165
try {
6266
final String json;
63-
final ObjectMapper objectMapper = new ObjectMapper();
6467
final RemoteApiVersion apiVersion = dockerClientConfig.getApiVersion();
6568

6669
if (apiVersion.equals(UNKNOWN_VERSION)) {

docker-java-transport-jersey/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import javax.ws.rs.client.WebTarget;
88
import javax.ws.rs.core.MediaType;
99

10-
import com.fasterxml.jackson.databind.ObjectMapper;
11-
1210
import com.github.dockerjava.core.util.CacheFromEncoder;
1311
import org.glassfish.jersey.client.ClientProperties;
1412
import org.glassfish.jersey.client.RequestEntityProcessing;
@@ -32,8 +30,6 @@ public class BuildImageCmdExec extends AbstrAsyncDockerCmdExec<BuildImageCmd, Bu
3230
BuildImageCmd.Exec {
3331
private static final Logger LOGGER = LoggerFactory.getLogger(BuildImageCmdExec.class);
3432

35-
private static final ObjectMapper MAPPER = new ObjectMapper();
36-
3733
public BuildImageCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) {
3834
super(baseResource, dockerClientConfig);
3935
}
@@ -137,7 +133,7 @@ protected AbstractCallbackNotifier<BuildResponseItem> callbackNotifier(BuildImag
137133

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

140-
return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(BuildResponseItem.class),
136+
return new POSTCallbackNotifier<>(new JsonStreamProcessor<>(objectMapper, BuildResponseItem.class),
141137
resultCallback,
142138
resourceWithOptionalAuthConfig(command, webTarget.request()).accept(MediaType.TEXT_PLAIN),
143139
entity(command.getTarInputStream(), "application/tar")
@@ -148,7 +144,7 @@ private WebTarget writeMap(WebTarget webTarget, String name, Map<String, String>
148144
if (value != null && !value.isEmpty()) {
149145
try {
150146
return webTarget.queryParam(name,
151-
URLEncoder.encode(MAPPER.writeValueAsString(value), "UTF-8").replaceAll("\\+", "%20"));
147+
URLEncoder.encode(objectMapper.writeValueAsString(value), "UTF-8").replaceAll("\\+", "%20"));
152148
} catch (IOException e) {
153149
throw new RuntimeException(e);
154150
}

0 commit comments

Comments
 (0)