Upgrade to Jackson 3.
Closes gh-919
This commit is contained in:
39
pom.xml
39
pom.xml
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.vault</groupId>
|
||||
@@ -33,7 +33,10 @@
|
||||
</google-auth-library-oauth2-http.version>
|
||||
<httpclient5.version>5.4.4</httpclient5.version>
|
||||
<httpcore5.version>5.3.4</httpcore5.version>
|
||||
<jackson-databind.version>2.19.0</jackson-databind.version>
|
||||
<jackson-annotations.version>3.0-rc5</jackson-annotations.version>
|
||||
<jackson-core.version>3.0.0-rc5</jackson-core.version>
|
||||
<jackson-databind.version>3.0.0-rc5</jackson-databind.version>
|
||||
<jackson2-databind.version>2.19.0</jackson2-databind.version>
|
||||
<jetty-reactive-httpclient.version>4.0.9</jetty-reactive-httpclient.version>
|
||||
<json-path.version>2.9.0</json-path.version>
|
||||
<junit.version>5.12.2</junit.version>
|
||||
@@ -44,7 +47,7 @@
|
||||
<netty.version>4.1.121.Final</netty.version>
|
||||
<nullaway.version>0.12.3</nullaway.version>
|
||||
<okhttp3.version>3.14.9</okhttp3.version>
|
||||
<spring.version>7.0.0-M2</spring.version>
|
||||
<spring.version>7.0.0-M5</spring.version>
|
||||
<spring-data-bom.version>2025.1.0-M1</spring-data-bom.version>
|
||||
<spring-security-bom.version>6.2.0</spring-security-bom.version>
|
||||
<reactor.version>2024.0.2</reactor.version>
|
||||
@@ -121,10 +124,28 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson-annotations.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson-core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-databind.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson2-databind.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
@@ -418,7 +439,10 @@
|
||||
<compilerArgs>
|
||||
<arg>-XDcompilePolicy=simple</arg>
|
||||
<arg>--should-stop=ifError=FLOW</arg>
|
||||
<arg>-Xplugin:ErrorProne -XepDisableAllChecks -Xep:NullAway:ERROR -XepOpt:NullAway:OnlyNullMarked=true -XepOpt:NullAway:CustomContractAnnotations=org.springframework.lang.Contract</arg>
|
||||
<arg>-Xplugin:ErrorProne -XepDisableAllChecks -Xep:NullAway:ERROR
|
||||
-XepOpt:NullAway:OnlyNullMarked=true
|
||||
-XepOpt:NullAway:CustomContractAnnotations=org.springframework.lang.Contract
|
||||
</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</execution>
|
||||
@@ -809,8 +833,9 @@
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<requireReleaseDeps />
|
||||
<NoSnapshotDependenciesInDependencyManagementRule implementation="de.smartics.maven.enforcer.rule.NoSnapshotsInDependencyManagementRule">
|
||||
<requireReleaseDeps/>
|
||||
<NoSnapshotDependenciesInDependencyManagementRule
|
||||
implementation="de.smartics.maven.enforcer.rule.NoSnapshotsInDependencyManagementRule">
|
||||
<onlyWhenRelease>true</onlyWhenRelease>
|
||||
</NoSnapshotDependenciesInDependencyManagementRule>
|
||||
</rules>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
@@ -77,7 +78,26 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Reactive support -->
|
||||
|
||||
@@ -23,8 +23,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentials;
|
||||
@@ -33,6 +31,7 @@ import software.amazon.awssdk.auth.signer.params.Aws4SignerParams;
|
||||
import software.amazon.awssdk.http.SdkHttpFullRequest;
|
||||
import software.amazon.awssdk.http.SdkHttpMethod;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -40,6 +39,7 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
@@ -75,8 +75,6 @@ public class AwsIamAuthentication implements ClientAuthentication, Authenticatio
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AwsIamAuthentication.class);
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private static final String REQUEST_BODY = "Action=GetCallerIdentity&Version=2011-06-15";
|
||||
|
||||
private static final String REQUEST_BODY_BASE64_ENCODED = Base64.getEncoder()
|
||||
@@ -229,12 +227,9 @@ public class AwsIamAuthentication implements ClientAuthentication, Authenticatio
|
||||
.build();
|
||||
SdkHttpFullRequest signedRequest = signer.sign(request, signerParams);
|
||||
|
||||
try {
|
||||
return OBJECT_MAPPER.writeValueAsString(new LinkedHashMap<>(signedRequest.headers()));
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new IllegalStateException("Cannot serialize headers to JSON", e);
|
||||
}
|
||||
return JacksonCompat.instance()
|
||||
.getObjectMapperAccessor()
|
||||
.writeValueAsString(new LinkedHashMap<>(signedRequest.headers()));
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> createIamRequestHeaders(AwsIamAuthenticationOptions options) {
|
||||
|
||||
@@ -25,9 +25,8 @@ import org.springframework.core.codec.ByteArrayEncoder;
|
||||
import org.springframework.core.codec.StringDecoder;
|
||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||
import org.springframework.http.codec.CodecConfigurer.CustomCodecs;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||
@@ -112,12 +111,11 @@ public class ReactiveVaultClients {
|
||||
CustomCodecs cc = configurer.customCodecs();
|
||||
|
||||
cc.register(new ByteArrayDecoder());
|
||||
cc.register(new Jackson2JsonDecoder());
|
||||
cc.register(StringDecoder.allMimeTypes());
|
||||
|
||||
cc.register(new ByteArrayEncoder());
|
||||
cc.register(new Jackson2JsonEncoder());
|
||||
|
||||
JacksonCompat.instance().registerCodecs(cc::register);
|
||||
}).build();
|
||||
|
||||
WebClient.Builder builder = WebClient.builder().exchangeStrategies(strategies).clientConnector(connector);
|
||||
|
||||
@@ -27,8 +27,10 @@ import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.DefaultUriBuilderFactory;
|
||||
import org.springframework.web.util.UriBuilder;
|
||||
@@ -104,14 +106,14 @@ public class VaultClients {
|
||||
* <p>
|
||||
* Requires Jackson 2 for Object-to-JSON mapping.
|
||||
* @return the {@link RestTemplate}.
|
||||
* @see MappingJackson2HttpMessageConverter
|
||||
* @see JacksonJsonHttpMessageConverter
|
||||
*/
|
||||
public static RestTemplate createRestTemplate() {
|
||||
|
||||
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(3);
|
||||
messageConverters.add(new ByteArrayHttpMessageConverter());
|
||||
messageConverters.add(new StringHttpMessageConverter());
|
||||
messageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||
messageConverters.add(JacksonCompat.instance().createHttpMessageConverter());
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate(messageConverters);
|
||||
|
||||
|
||||
@@ -23,16 +23,15 @@ import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
|
||||
@@ -43,10 +42,8 @@ import org.springframework.web.client.HttpStatusCodeException;
|
||||
*/
|
||||
public abstract class VaultResponses {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private static final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(
|
||||
OBJECT_MAPPER);
|
||||
private static final AbstractHttpMessageConverter<Object> converter = JacksonCompat.instance()
|
||||
.createHttpMessageConverter();
|
||||
|
||||
/**
|
||||
* Build a {@link VaultException} given {@link HttpStatusCodeException}.
|
||||
@@ -146,20 +143,16 @@ public abstract class VaultResponses {
|
||||
|
||||
if (json.contains("\"errors\":")) {
|
||||
|
||||
try {
|
||||
Map<String, Object> map = OBJECT_MAPPER.readValue(json.getBytes(), Map.class);
|
||||
if (map.containsKey("errors")) {
|
||||
Map<String, Object> map = JacksonCompat.instance()
|
||||
.getObjectMapperAccessor()
|
||||
.deserialize(json.getBytes(), Map.class);
|
||||
if (map.containsKey("errors")) {
|
||||
|
||||
Collection<String> errors = (Collection<String>) map.get("errors");
|
||||
if (errors.size() == 1) {
|
||||
return errors.iterator().next();
|
||||
}
|
||||
return errors.toString();
|
||||
Collection<String> errors = (Collection<String>) map.get("errors");
|
||||
if (errors.size() == 1) {
|
||||
return errors.iterator().next();
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException o_O) {
|
||||
// ignore
|
||||
return errors.toString();
|
||||
}
|
||||
}
|
||||
return json;
|
||||
|
||||
@@ -17,9 +17,9 @@ package org.springframework.vault.core;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.core.VaultKeyValueOperationsSupport.KeyValueBackend;
|
||||
@@ -103,7 +103,7 @@ class ReactiveVaultKeyValue1Template extends ReactiveVaultKeyValueAccessor imple
|
||||
}
|
||||
|
||||
@Override
|
||||
JsonNode getJsonNode(VaultResponseSupport<JsonNode> response) {
|
||||
Object getJsonNode(VaultResponseSupport<Object> response) {
|
||||
return response.getRequiredData();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ package org.springframework.vault.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.vault.core.VaultKeyValueOperationsSupport.KeyValueBackend;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
@@ -68,8 +68,8 @@ abstract class ReactiveVaultKeyValue2Accessor extends ReactiveVaultKeyValueAcces
|
||||
}
|
||||
|
||||
@Override
|
||||
JsonNode getJsonNode(VaultResponseSupport<JsonNode> response) {
|
||||
return response.getRequiredData().at("/data");
|
||||
Object getJsonNode(VaultResponseSupport<Object> response) {
|
||||
return JacksonCompat.instance().getAt(response.getRequiredData(), "/data");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,13 +15,10 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -31,15 +28,15 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
|
||||
|
||||
import static org.springframework.vault.core.ReactiveVaultTemplate.*;
|
||||
import static org.springframework.vault.core.ReactiveVaultTemplate.mapResponse;
|
||||
|
||||
/**
|
||||
* Base class for {@link ReactiveVaultVersionedKeyValueTemplate} and
|
||||
@@ -59,7 +56,7 @@ abstract class ReactiveVaultKeyValueAccessor implements ReactiveVaultKeyValueOpe
|
||||
|
||||
private final String path;
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
private final JacksonCompat.ObjectMapperAccessor mapper;
|
||||
|
||||
/**
|
||||
* Create a new {@link ReactiveVaultKeyValueAccessor} given
|
||||
@@ -74,6 +71,7 @@ abstract class ReactiveVaultKeyValueAccessor implements ReactiveVaultKeyValueOpe
|
||||
|
||||
this.reactiveVaultOperations = reactiveVaultOperations;
|
||||
this.path = path;
|
||||
this.mapper = JacksonCompat.instance().getObjectMapperAccessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,18 +101,16 @@ abstract class ReactiveVaultKeyValueAccessor implements ReactiveVaultKeyValueOpe
|
||||
<I, T> Mono<T> doRead(String path, Class<I> deserializeAs,
|
||||
BiFunction<VaultResponseSupport<?>, I, T> mappingFunction) {
|
||||
|
||||
ParameterizedTypeReference<VaultResponseSupport<JsonNode>> ref = VaultResponses
|
||||
.getTypeReference(JsonNode.class);
|
||||
ParameterizedTypeReference<VaultResponseSupport<Object>> ref = VaultResponses
|
||||
.getTypeReference(JacksonCompat.instance().getJsonNodeClass());
|
||||
|
||||
Mono<VaultResponseSupport<JsonNode>> response = doRead(createDataPath(path), ref);
|
||||
Mono<VaultResponseSupport<Object>> response = doRead(createDataPath(path), ref);
|
||||
|
||||
return response.map(it -> {
|
||||
|
||||
JsonNode jsonNode = getJsonNode(it);
|
||||
JsonNode jsonMeta = it.getRequiredData().at("/metadata");
|
||||
it.setMetadata(this.mapper.convertValue(jsonMeta, new TypeReference<>() {
|
||||
}));
|
||||
|
||||
Object jsonNode = getJsonNode(it);
|
||||
Object jsonMeta = JacksonCompat.instance().getAt(it.getRequiredData(), "/metadata");
|
||||
it.setMetadata(this.mapper.deserialize(jsonMeta, Map.class));
|
||||
return mappingFunction.apply(it, deserialize(jsonNode, deserializeAs));
|
||||
});
|
||||
}
|
||||
@@ -144,19 +140,13 @@ abstract class ReactiveVaultKeyValueAccessor implements ReactiveVaultKeyValueOpe
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a {@link JsonNode} to the requested {@link Class type}.
|
||||
* Deserialize a {@code JsonNode} to the requested {@link Class type}.
|
||||
* @param jsonNode must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return the deserialized object.
|
||||
*/
|
||||
<T> T deserialize(JsonNode jsonNode, Class<T> type) {
|
||||
|
||||
try {
|
||||
return this.mapper.reader().readValue(jsonNode.traverse(), type);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot deserialize response", e);
|
||||
}
|
||||
<T> T deserialize(Object jsonNode, Class<T> type) {
|
||||
return this.mapper.deserialize(jsonNode, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,11 +175,11 @@ abstract class ReactiveVaultKeyValueAccessor implements ReactiveVaultKeyValueOpe
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link JsonNode} that contains the actual response body.
|
||||
* Return the {@code JsonNode} that contains the actual response body.
|
||||
* @param response the response to extract the appropriate node from.
|
||||
* @return the extracted {@link JsonNode}.
|
||||
* @return the extracted {@code JsonNode}.
|
||||
*/
|
||||
abstract JsonNode getJsonNode(VaultResponseSupport<JsonNode> response);
|
||||
abstract Object getJsonNode(VaultResponseSupport<Object> response);
|
||||
|
||||
/**
|
||||
* @param path must not be {@literal null} or empty.
|
||||
|
||||
@@ -23,12 +23,12 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.vault.support.Versioned;
|
||||
import org.springframework.vault.support.Versioned.Metadata;
|
||||
@@ -90,11 +90,20 @@ public class ReactiveVaultVersionedKeyValueTemplate extends ReactiveVaultKeyValu
|
||||
String secretPath = version.isVersioned()
|
||||
? "%s?version=%d".formatted(createDataPath(path), version.getVersion()) : createDataPath(path);
|
||||
|
||||
Mono<VersionedResponse> versionedResponseMono = doReadVersioned(secretPath);
|
||||
Class<? extends VaultResponseSupport> responseTypeToUse;
|
||||
if (JacksonCompat.instance().isJackson3()) {
|
||||
responseTypeToUse = VersionedResponse.class;
|
||||
}
|
||||
else {
|
||||
responseTypeToUse = VersionedJackson2Response.class;
|
||||
}
|
||||
|
||||
Mono<VaultResponseSupport<VaultResponseSupport<Object>>> versionedResponseMono = (Mono) doReadVersioned(
|
||||
secretPath, responseTypeToUse);
|
||||
|
||||
return versionedResponseMono.map(response -> {
|
||||
|
||||
VaultResponseSupport<JsonNode> data = response.getRequiredData();
|
||||
VaultResponseSupport<Object> data = response.getRequiredData();
|
||||
Metadata metadata = KeyValueUtilities.getMetadata(data.getMetadata());
|
||||
|
||||
T body = deserialize(data.getRequiredData(), responseType);
|
||||
@@ -175,19 +184,18 @@ public class ReactiveVaultVersionedKeyValueTemplate extends ReactiveVaultKeyValu
|
||||
* @param path must not be {@literal null} or empty.
|
||||
* @return mapped value.
|
||||
*/
|
||||
<T> Mono<VersionedResponse> doReadVersioned(String path) {
|
||||
<T> Mono<T> doReadVersioned(String path, Class<T> responseType) {
|
||||
|
||||
Function<ClientResponse, Mono<ResponseEntity<VersionedResponse>>> toEntity = cr -> cr
|
||||
.toEntity(VersionedResponse.class);
|
||||
ResponseFunction<VersionedResponse> defaults = new ResponseFunction<>(toEntity);
|
||||
Function<ClientResponse, Mono<VersionedResponse>> responseFunction = clientResponse -> {
|
||||
Function<ClientResponse, Mono<ResponseEntity<T>>> toEntity = cr -> cr.toEntity(responseType);
|
||||
ResponseFunction<T> defaults = new ResponseFunction<>(toEntity);
|
||||
Function<ClientResponse, Mono<T>> responseFunction = clientResponse -> {
|
||||
|
||||
if (HttpStatusUtil.isNotFound(clientResponse.statusCode())) {
|
||||
|
||||
return clientResponse.bodyToMono(String.class).flatMap(it -> {
|
||||
|
||||
if (it.contains("deletion_time")) {
|
||||
return Mono.justOrEmpty(VaultResponses.unwrap(it, VersionedResponse.class));
|
||||
return Mono.justOrEmpty(VaultResponses.unwrap(it, responseType));
|
||||
}
|
||||
|
||||
return Mono.empty();
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.vault.core;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
@@ -108,7 +107,7 @@ class VaultKeyValue1Template extends VaultKeyValueAccessor implements VaultKeyVa
|
||||
}
|
||||
|
||||
@Override
|
||||
JsonNode getJsonNode(VaultResponseSupport<JsonNode> response) {
|
||||
Object getJsonNode(VaultResponseSupport<Object> response) {
|
||||
return response.getRequiredData();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ package org.springframework.vault.core;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
@@ -71,8 +71,8 @@ abstract class VaultKeyValue2Accessor extends VaultKeyValueAccessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
JsonNode getJsonNode(VaultResponseSupport<JsonNode> response) {
|
||||
return response.getRequiredData().at("/data");
|
||||
Object getJsonNode(VaultResponseSupport<Object> response) {
|
||||
return JacksonCompat.instance().getAt(response.getRequiredData(), "/data");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,15 +15,10 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
@@ -31,15 +26,13 @@ import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class for {@link VaultVersionedKeyValueTemplate} and
|
||||
@@ -57,7 +50,7 @@ abstract class VaultKeyValueAccessor implements VaultKeyValueOperationsSupport {
|
||||
|
||||
private final String path;
|
||||
|
||||
private final ObjectMapper mapper;
|
||||
private final JacksonCompat.ObjectMapperAccessor mapper;
|
||||
|
||||
/**
|
||||
* Create a new {@link VaultKeyValueAccessor} given {@link VaultOperations} and the
|
||||
@@ -72,7 +65,7 @@ abstract class VaultKeyValueAccessor implements VaultKeyValueOperationsSupport {
|
||||
|
||||
this.vaultOperations = vaultOperations;
|
||||
this.path = path;
|
||||
this.mapper = extractObjectMapper(vaultOperations);
|
||||
this.mapper = JacksonCompat.ObjectMapperAccessor.from(vaultOperations);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,17 +95,16 @@ abstract class VaultKeyValueAccessor implements VaultKeyValueOperationsSupport {
|
||||
<I, T> @Nullable T doRead(String path, Class<I> deserializeAs,
|
||||
BiFunction<VaultResponseSupport<?>, I, T> mappingFunction) {
|
||||
|
||||
ParameterizedTypeReference<VaultResponseSupport<JsonNode>> ref = VaultResponses
|
||||
.getTypeReference(JsonNode.class);
|
||||
ParameterizedTypeReference<VaultResponseSupport<Object>> ref = VaultResponses
|
||||
.getTypeReference(JacksonCompat.instance().getJsonNodeClass());
|
||||
|
||||
VaultResponseSupport<JsonNode> response = doRead(createDataPath(path), ref);
|
||||
VaultResponseSupport<Object> response = doRead(createDataPath(path), ref);
|
||||
|
||||
if (response != null) {
|
||||
|
||||
JsonNode jsonNode = getJsonNode(response);
|
||||
JsonNode jsonMeta = response.getRequiredData().at("/metadata");
|
||||
response.setMetadata(this.mapper.convertValue(jsonMeta, new TypeReference<>() {
|
||||
}));
|
||||
Object jsonNode = getJsonNode(response);
|
||||
Object jsonMeta = JacksonCompat.instance().getAt(response.getRequiredData(), "/metadata");
|
||||
response.setMetadata(this.mapper.deserialize(jsonMeta, Map.class));
|
||||
|
||||
return mappingFunction.apply(response, deserialize(jsonNode, deserializeAs));
|
||||
}
|
||||
@@ -135,19 +127,13 @@ abstract class VaultKeyValueAccessor implements VaultKeyValueOperationsSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a {@link JsonNode} to the requested {@link Class type}.
|
||||
* Deserialize a {@code JsonNode} to the requested {@link Class type}.
|
||||
* @param jsonNode must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return the deserialized object.
|
||||
*/
|
||||
<T> T deserialize(JsonNode jsonNode, Class<T> type) {
|
||||
|
||||
try {
|
||||
return this.mapper.reader().readValue(jsonNode.traverse(), type);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot deserialize response", e);
|
||||
}
|
||||
<T> T deserialize(Object jsonNode, Class<T> type) {
|
||||
return this.mapper.deserialize(jsonNode, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,11 +188,11 @@ abstract class VaultKeyValueAccessor implements VaultKeyValueOperationsSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link JsonNode} that contains the actual response body.
|
||||
* Return the {@code JsonNode} that contains the actual response body.
|
||||
* @param response the response to extract the appropriate node from.
|
||||
* @return the extracted {@link JsonNode}.
|
||||
* @return the extracted {@code JsonNode}.
|
||||
*/
|
||||
abstract JsonNode getJsonNode(VaultResponseSupport<JsonNode> response);
|
||||
abstract Object getJsonNode(VaultResponseSupport<Object> response);
|
||||
|
||||
/**
|
||||
* @param path must not be {@literal null} or empty.
|
||||
@@ -214,25 +200,4 @@ abstract class VaultKeyValueAccessor implements VaultKeyValueOperationsSupport {
|
||||
*/
|
||||
abstract String createDataPath(String path);
|
||||
|
||||
private static ObjectMapper extractObjectMapper(VaultOperations vaultOperations) {
|
||||
|
||||
Optional<ObjectMapper> mapper = vaultOperations.doWithSession(operations -> {
|
||||
|
||||
if (operations instanceof RestTemplate template) {
|
||||
|
||||
Optional<AbstractJackson2HttpMessageConverter> jackson2Converter = template.getMessageConverters()
|
||||
.stream()
|
||||
.filter(AbstractJackson2HttpMessageConverter.class::isInstance) //
|
||||
.map(AbstractJackson2HttpMessageConverter.class::cast) //
|
||||
.findFirst();
|
||||
|
||||
return jackson2Converter.map(AbstractJackson2HttpMessageConverter::getObjectMapper);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
});
|
||||
|
||||
return Objects.requireNonNull(mapper).orElseGet(ObjectMapper::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -27,8 +26,6 @@ import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
@@ -41,6 +38,7 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultHttpHeaders;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.Policy;
|
||||
import org.springframework.vault.support.VaultHealth;
|
||||
import org.springframework.vault.support.VaultInitializationRequest;
|
||||
@@ -72,15 +70,6 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
private static final Health HEALTH = new Health();
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER;
|
||||
|
||||
static {
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
OBJECT_MAPPER = mapper;
|
||||
}
|
||||
|
||||
private final VaultOperations vaultOperations;
|
||||
|
||||
/**
|
||||
@@ -264,12 +253,7 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
String rules;
|
||||
|
||||
try {
|
||||
rules = OBJECT_MAPPER.writeValueAsString(policy);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot serialize policy to JSON", e);
|
||||
}
|
||||
rules = JacksonCompat.instance().getPrettyPrintObjectMapperAccessor().writeValueAsString(policy);
|
||||
|
||||
this.vaultOperations.doWithSession((RestOperationsCallback<@Nullable Void>) restOperations -> {
|
||||
|
||||
@@ -341,6 +325,7 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
return body.getTopLevelMounts();
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
private static class VaultMountsResponse extends VaultResponseSupport<Map<String, VaultMount>> {
|
||||
|
||||
private final Map<String, VaultMount> topLevelMounts = new HashMap<>();
|
||||
@@ -399,7 +384,9 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
catch (RestClientResponseException responseError) {
|
||||
|
||||
try {
|
||||
return OBJECT_MAPPER.readValue(responseError.getResponseBodyAsString(), VaultHealthImpl.class);
|
||||
return JacksonCompat.instance()
|
||||
.getObjectMapperAccessor()
|
||||
.deserialize(responseError.getResponseBodyAsString(), VaultHealthImpl.class);
|
||||
}
|
||||
catch (Exception jsonError) {
|
||||
throw responseError;
|
||||
@@ -409,6 +396,7 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
static class VaultInitializationResponseImpl implements VaultInitializationResponse {
|
||||
|
||||
private List<String> keys = new ArrayList<>();
|
||||
@@ -451,6 +439,7 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
static class VaultUnsealStatusImpl implements VaultUnsealStatus {
|
||||
|
||||
private boolean sealed;
|
||||
|
||||
@@ -22,12 +22,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.JacksonCompat;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.vault.support.Versioned;
|
||||
@@ -92,17 +92,25 @@ public class VaultVersionedKeyValueTemplate extends VaultKeyValue2Accessor imple
|
||||
String secretPath = version.isVersioned()
|
||||
? "%s?version=%d".formatted(createDataPath(path), version.getVersion()) : createDataPath(path);
|
||||
|
||||
VersionedResponse response = this.vaultOperations
|
||||
.doWithSession((RestOperationsCallback<@Nullable VersionedResponse>) restOperations -> {
|
||||
Class<? extends VaultResponseSupport> responseTypeToUse;
|
||||
if (JacksonCompat.instance().isJackson3()) {
|
||||
responseTypeToUse = VersionedResponse.class;
|
||||
}
|
||||
else {
|
||||
responseTypeToUse = VersionedJackson2Response.class;
|
||||
}
|
||||
|
||||
VaultResponseSupport<VaultResponseSupport<Object>> response = this.vaultOperations
|
||||
.doWithSession((RestOperationsCallback<@Nullable VaultResponseSupport>) restOperations -> {
|
||||
|
||||
try {
|
||||
return restOperations.exchange(secretPath, HttpMethod.GET, null, VersionedResponse.class).getBody();
|
||||
return restOperations.exchange(secretPath, HttpMethod.GET, null, responseTypeToUse).getBody();
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
|
||||
if (HttpStatusUtil.isNotFound(e.getStatusCode())) {
|
||||
if (e.getResponseBodyAsString().contains("deletion_time")) {
|
||||
return VaultResponses.unwrap(e.getResponseBodyAsString(), VersionedResponse.class);
|
||||
return VaultResponses.unwrap(e.getResponseBodyAsString(), responseTypeToUse);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -116,7 +124,7 @@ public class VaultVersionedKeyValueTemplate extends VaultKeyValue2Accessor imple
|
||||
return null;
|
||||
}
|
||||
|
||||
VaultResponseSupport<JsonNode> data = response.getRequiredData();
|
||||
VaultResponseSupport<Object> data = response.getRequiredData();
|
||||
Metadata metadata = KeyValueUtilities.getMetadata(data.getMetadata());
|
||||
|
||||
T body = deserialize(data.getRequiredData(), responseType);
|
||||
|
||||
@@ -13,23 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.util.Base64;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import com.fasterxml.jackson.databind.util.StdConverter;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
* Converts Plaintext to Base64 encoded string for use with
|
||||
* {@link com.fasterxml.jackson.databind.ObjectMapper}
|
||||
*
|
||||
* @author James Luke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class PlaintextToBase64StringConverter extends StdConverter<Plaintext, String> {
|
||||
|
||||
@Override
|
||||
public String convert(Plaintext plaintext) {
|
||||
return Base64.getEncoder().encodeToString(plaintext.getPlaintext());
|
||||
}
|
||||
@Deprecated(forRemoval = true)
|
||||
class VersionedJackson2Response extends VaultResponseSupport<VaultResponseSupport<JsonNode>> {
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tools.jackson.core.ObjectReadContext;
|
||||
import tools.jackson.core.json.JsonWriteFeature;
|
||||
import tools.jackson.databind.ObjectReader;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.http.codec.json.JacksonJsonDecoder;
|
||||
import org.springframework.http.codec.json.JacksonJsonEncoder;
|
||||
import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||
import org.springframework.http.converter.AbstractJacksonHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Compatibility layer for Jackson 2 and Jackson 3. This class auto-detects whether
|
||||
* Jackson 3 or Jackson 2 are available prefering Jackson 3. Note that Jackson 2 support
|
||||
* will be removed in future versions.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("ALL")
|
||||
public abstract class JacksonCompat {
|
||||
|
||||
static final @Nullable Class JACKSON_2_JSON_NODE;
|
||||
static final @Nullable Class JACKSON_3_JSON_NODE;
|
||||
static final JacksonCompat compat;
|
||||
|
||||
static {
|
||||
|
||||
Class<?> jackson2JsonNode = null;
|
||||
Class<?> jackson3JsonNode = null;
|
||||
try {
|
||||
jackson2JsonNode = ClassUtils
|
||||
.isPresent("com.fasterxml.jackson.databind.JsonNode", Jackson2.class.getClassLoader())
|
||||
? ClassUtils.forName("com.fasterxml.jackson.databind.JsonNode", Jackson2.class.getClassLoader())
|
||||
: null;
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
jackson3JsonNode = ClassUtils.isPresent("tools.jackson.databind.JsonNode", Jackson2.class.getClassLoader())
|
||||
? ClassUtils.forName("tools.jackson.databind.JsonNode", Jackson2.class.getClassLoader()) : null;
|
||||
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
}
|
||||
|
||||
JACKSON_2_JSON_NODE = jackson2JsonNode;
|
||||
JACKSON_3_JSON_NODE = jackson3JsonNode;
|
||||
|
||||
if (JACKSON_3_JSON_NODE != null) {
|
||||
compat = Jackson3.INSTANCE;
|
||||
}
|
||||
else if (JACKSON_2_JSON_NODE != null) {
|
||||
compat = Jackson2.INSTANCE;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Either Jackson 2 or Jackson 3 must be available on the classpath");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the {@link JacksonCompat} instance.
|
||||
* @return
|
||||
*/
|
||||
public static JacksonCompat instance() {
|
||||
return compat;
|
||||
}
|
||||
|
||||
public boolean isJackson3() {
|
||||
return this instanceof Jackson3;
|
||||
}
|
||||
|
||||
public abstract AbstractHttpMessageConverter<Object> createHttpMessageConverter();
|
||||
|
||||
public abstract void registerCodecs(Consumer<Object> messageConverters);
|
||||
|
||||
public abstract Class<Object> getJsonNodeClass();
|
||||
|
||||
public abstract Object getAt(Object jsonNode, String path);
|
||||
|
||||
public abstract ObjectMapperAccessor getObjectMapperAccessor();
|
||||
|
||||
public abstract ObjectMapperAccessor getPrettyPrintObjectMapperAccessor();
|
||||
|
||||
public abstract @Nullable ObjectMapperAccessor getObjectMapperAccessor(
|
||||
List<HttpMessageConverter<?>> messageConverters);
|
||||
|
||||
/**
|
||||
* Accessor for {@code ObjectMapper} that provides methods to serialize and
|
||||
* deserialize JSON.
|
||||
*/
|
||||
public interface ObjectMapperAccessor {
|
||||
|
||||
static ObjectMapperAccessor create() {
|
||||
return compat.getObjectMapperAccessor();
|
||||
}
|
||||
|
||||
static ObjectMapperAccessor from(VaultOperations vaultOperations) {
|
||||
|
||||
return vaultOperations.doWithSession(operations -> {
|
||||
|
||||
if (operations instanceof RestTemplate template) {
|
||||
|
||||
ObjectMapperAccessor accessor = compat.getObjectMapperAccessor(template.getMessageConverters());
|
||||
|
||||
if (accessor != null) {
|
||||
return accessor;
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectMapperAccessor.create();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a {@code JsonNode} to the requested {@link Class type}.
|
||||
* @param json must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return the deserialized object.
|
||||
*/
|
||||
<I> I deserialize(Object json, Class<I> type);
|
||||
|
||||
String writeValueAsString(Object object);
|
||||
|
||||
}
|
||||
|
||||
static class Jackson2 extends JacksonCompat {
|
||||
|
||||
static final Jackson2 INSTANCE = new Jackson2();
|
||||
static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
static final ObjectMapper PRETTY_PRINT_OBJECT_MAPPER = new ObjectMapper()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
static final Jackson2ObjectMapperAccessor MAPPER_ACCESSOR = new Jackson2ObjectMapperAccessor(OBJECT_MAPPER);
|
||||
|
||||
static final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(
|
||||
OBJECT_MAPPER);
|
||||
|
||||
public static boolean isAvailable() {
|
||||
return JACKSON_2_JSON_NODE != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractHttpMessageConverter<Object> createHttpMessageConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCodecs(Consumer<Object> messageConverters) {
|
||||
|
||||
messageConverters.accept(new Jackson2JsonDecoder(OBJECT_MAPPER));
|
||||
messageConverters.accept(new Jackson2JsonEncoder(OBJECT_MAPPER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Object> getJsonNodeClass() {
|
||||
return Objects.requireNonNull(JACKSON_2_JSON_NODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAt(Object jsonNode, String path) {
|
||||
return ((JsonNode) jsonNode).at(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectMapperAccessor getObjectMapperAccessor() {
|
||||
return MAPPER_ACCESSOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectMapperAccessor getPrettyPrintObjectMapperAccessor() {
|
||||
return new Jackson2ObjectMapperAccessor(PRETTY_PRINT_OBJECT_MAPPER);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public @Nullable ObjectMapperAccessor getObjectMapperAccessor(List<HttpMessageConverter<?>> converters) {
|
||||
|
||||
Optional<AbstractJackson2HttpMessageConverter> jackson2Converter = converters.stream()
|
||||
.filter(AbstractJackson2HttpMessageConverter.class::isInstance) //
|
||||
.map(AbstractJackson2HttpMessageConverter.class::cast) //
|
||||
.findFirst();
|
||||
|
||||
return jackson2Converter.map(AbstractJackson2HttpMessageConverter::getObjectMapper)
|
||||
.map(Jackson2ObjectMapperAccessor::new)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
static class Jackson2ObjectMapperAccessor implements ObjectMapperAccessor {
|
||||
|
||||
private final com.fasterxml.jackson.databind.ObjectMapper mapper;
|
||||
|
||||
Jackson2ObjectMapperAccessor(ObjectMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
public com.fasterxml.jackson.core.TreeNode getJsonNode(Object jsonNode) {
|
||||
return (com.fasterxml.jackson.databind.JsonNode) jsonNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <I> I deserialize(Object json, Class<I> type) {
|
||||
try {
|
||||
|
||||
if (json instanceof String s) {
|
||||
return this.mapper.reader().readValue(s, type);
|
||||
}
|
||||
|
||||
if (json instanceof byte[] bs) {
|
||||
return this.mapper.reader().readValue(bs, type);
|
||||
}
|
||||
|
||||
return this.mapper.reader().readValue(getJsonNode(json).traverse(), type);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot deserialize response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String writeValueAsString(Object object) {
|
||||
try {
|
||||
return mapper.writeValueAsString(object);
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new IllegalStateException("Cannot serialize headers to JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Jackson3 extends JacksonCompat {
|
||||
|
||||
static final Jackson3 INSTANCE = new Jackson3();
|
||||
|
||||
static final tools.jackson.databind.ObjectMapper OBJECT_MAPPER = new tools.jackson.databind.ObjectMapper();
|
||||
static final tools.jackson.databind.ObjectMapper PRETTY_PRINT_OBJECT_MAPPER = JsonMapper.builder()
|
||||
.enable(tools.jackson.databind.SerializationFeature.INDENT_OUTPUT)
|
||||
.disable(JsonWriteFeature.ESCAPE_FORWARD_SLASHES)
|
||||
.build();
|
||||
static final Jackson3ObjectMapperAccessor MAPPER_ACCESSOR = new Jackson3ObjectMapperAccessor(
|
||||
PRETTY_PRINT_OBJECT_MAPPER);
|
||||
|
||||
static final JacksonJsonHttpMessageConverter converter = new JacksonJsonHttpMessageConverter(OBJECT_MAPPER);
|
||||
|
||||
public static boolean isAvailable() {
|
||||
return JACKSON_3_JSON_NODE != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractHttpMessageConverter<Object> createHttpMessageConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCodecs(Consumer<Object> messageConverters) {
|
||||
|
||||
messageConverters.accept(new JacksonJsonDecoder(OBJECT_MAPPER));
|
||||
messageConverters.accept(new JacksonJsonEncoder(OBJECT_MAPPER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Object> getJsonNodeClass() {
|
||||
return Objects.requireNonNull(JACKSON_3_JSON_NODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAt(Object jsonNode, String path) {
|
||||
return ((tools.jackson.databind.JsonNode) jsonNode).at(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectMapperAccessor getObjectMapperAccessor() {
|
||||
return new Jackson3.Jackson3ObjectMapperAccessor(OBJECT_MAPPER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectMapperAccessor getPrettyPrintObjectMapperAccessor() {
|
||||
return MAPPER_ACCESSOR;
|
||||
}
|
||||
|
||||
public @Nullable ObjectMapperAccessor getObjectMapperAccessor(List<HttpMessageConverter<?>> converters) {
|
||||
|
||||
Optional<AbstractJacksonHttpMessageConverter> jackson3Converter = converters.stream()
|
||||
.filter(AbstractJacksonHttpMessageConverter.class::isInstance) //
|
||||
.map(AbstractJacksonHttpMessageConverter.class::cast) //
|
||||
.findFirst();
|
||||
|
||||
return jackson3Converter.map(AbstractJacksonHttpMessageConverter::getObjectMapper)
|
||||
.map(Jackson3.Jackson3ObjectMapperAccessor::new)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
static class Jackson3ObjectMapperAccessor implements ObjectMapperAccessor {
|
||||
|
||||
private final tools.jackson.databind.ObjectMapper mapper;
|
||||
|
||||
Jackson3ObjectMapperAccessor(tools.jackson.databind.ObjectMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
public tools.jackson.databind.JsonNode getJsonNode(Object jsonNode) {
|
||||
return (tools.jackson.databind.JsonNode) jsonNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <I> I deserialize(Object json, Class<I> type) {
|
||||
|
||||
ObjectReader reader = this.mapper.readerFor(type);
|
||||
|
||||
if (json instanceof String s) {
|
||||
return reader.readValue(s);
|
||||
}
|
||||
|
||||
if (json instanceof byte[] bs) {
|
||||
return reader.readValue(bs);
|
||||
}
|
||||
|
||||
return reader.readValue(getJsonNode(json).traverse(ObjectReadContext.empty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String writeValueAsString(Object object) {
|
||||
return mapper.writeValueAsString(object);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -27,8 +26,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
@@ -36,24 +33,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
import com.fasterxml.jackson.databind.util.Converter;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.annotation.JsonDeserialize;
|
||||
import tools.jackson.databind.annotation.JsonSerialize;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.support.Policy.PolicyDeserializer;
|
||||
import org.springframework.vault.support.Policy.PolicySerializer;
|
||||
|
||||
/**
|
||||
* Value object representing a Vault policy associated with {@link Rule}s. Instances of
|
||||
@@ -61,11 +47,13 @@ import org.springframework.vault.support.Policy.PolicySerializer;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see Rule
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper
|
||||
* @see ObjectMapper
|
||||
* @since 2.0
|
||||
*/
|
||||
@JsonSerialize(using = PolicySerializer.class)
|
||||
@JsonDeserialize(using = PolicyDeserializer.class)
|
||||
@JsonSerialize(using = PolicyJackson3.PolicySerializer.class)
|
||||
@JsonDeserialize(using = PolicyJackson3.PolicyDeserializer.class)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = PolicyJackson2.PolicySerializer.class)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = PolicyJackson2.PolicyDeserializer.class)
|
||||
public class Policy {
|
||||
|
||||
private static final Policy EMPTY = new Policy(Collections.emptySet());
|
||||
@@ -184,8 +172,12 @@ public class Policy {
|
||||
* One or more capabilities which provide fine-grained control over permitted (or
|
||||
* denied) operations.
|
||||
*/
|
||||
@JsonSerialize(contentConverter = CapabilityToStringConverter.class)
|
||||
@JsonDeserialize(contentConverter = StringToCapabilityConverter.class)
|
||||
@JsonSerialize(contentConverter = PolicyJackson3.CapabilityToStringConverter.class)
|
||||
@JsonDeserialize(contentConverter = PolicyJackson3.StringToCapabilityConverter.class)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonSerialize(
|
||||
contentConverter = PolicyJackson2.CapabilityToStringConverter.class)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(
|
||||
contentConverter = PolicyJackson2.StringToCapabilityConverter.class)
|
||||
private final List<Capability> capabilities;
|
||||
|
||||
/**
|
||||
@@ -194,7 +186,9 @@ public class Policy {
|
||||
* wrapping mandatory for a particular path.
|
||||
*/
|
||||
@JsonProperty("min_wrapping_ttl")
|
||||
@JsonSerialize(converter = DurationToStringConverter.class)
|
||||
@JsonSerialize(converter = PolicyJackson3.DurationToStringConverter.class)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonSerialize(
|
||||
converter = PolicyJackson2.DurationToStringConverter.class)
|
||||
@Nullable
|
||||
private final Duration minWrappingTtl;
|
||||
|
||||
@@ -202,7 +196,9 @@ public class Policy {
|
||||
* The maximum allowed TTL that clients can specify for a wrapped response.
|
||||
*/
|
||||
@JsonProperty("max_wrapping_ttl")
|
||||
@JsonSerialize(converter = DurationToStringConverter.class)
|
||||
@JsonSerialize(converter = PolicyJackson3.DurationToStringConverter.class)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonSerialize(
|
||||
converter = PolicyJackson2.DurationToStringConverter.class)
|
||||
@Nullable
|
||||
private final Duration maxWrappingTtl;
|
||||
|
||||
@@ -226,9 +222,11 @@ public class Policy {
|
||||
@JsonCreator
|
||||
private Rule(@JsonProperty("capabilities") List<Capability> capabilities,
|
||||
@JsonProperty("min_wrapping_ttl") @JsonDeserialize(
|
||||
converter = StringToDurationConverter.class) Duration minWrappingTtl,
|
||||
converter = PolicyJackson3.StringToDurationConverter.class) @com.fasterxml.jackson.databind.annotation.JsonDeserialize(
|
||||
converter = PolicyJackson2.StringToDurationConverter.class) Duration minWrappingTtl,
|
||||
@JsonProperty("max_wrapping_ttl") @JsonDeserialize(
|
||||
converter = StringToDurationConverter.class) Duration maxWrappingTtl,
|
||||
converter = PolicyJackson3.StringToDurationConverter.class) @com.fasterxml.jackson.databind.annotation.JsonDeserialize(
|
||||
converter = PolicyJackson2.StringToDurationConverter.class) Duration maxWrappingTtl,
|
||||
@JsonProperty("allowed_parameters") Map<String, List<String>> allowedParameters,
|
||||
@JsonProperty("denied_parameters") Map<String, List<String>> deniedParameters) {
|
||||
|
||||
@@ -260,7 +258,7 @@ public class Policy {
|
||||
return new RuleBuilder();
|
||||
}
|
||||
|
||||
private Rule withPath(String path) {
|
||||
Rule withPath(String path) {
|
||||
return new Rule(path, this.capabilities, this.minWrappingTtl, this.maxWrappingTtl, this.allowedParameters,
|
||||
this.deniedParameters);
|
||||
}
|
||||
@@ -312,7 +310,7 @@ public class Policy {
|
||||
|
||||
private @Nullable String path;
|
||||
|
||||
private Set<Capability> capabilities = new LinkedHashSet<>();
|
||||
private final Set<Capability> capabilities = new LinkedHashSet<>();
|
||||
|
||||
@Nullable
|
||||
private Duration minWrappingTtl;
|
||||
@@ -320,11 +318,9 @@ public class Policy {
|
||||
@Nullable
|
||||
private Duration maxWrappingTtl;
|
||||
|
||||
private Map<String, List<String>> allowedParameters = new LinkedHashMap<String, List<String>>();
|
||||
private final Map<String, List<String>> allowedParameters = new LinkedHashMap<>();
|
||||
|
||||
private Map<String, List<String>> deniedParameters = new LinkedHashMap<String, List<String>>();
|
||||
|
||||
;
|
||||
private final Map<String, List<String>> deniedParameters = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* Associate a {@code path} with the rule.
|
||||
@@ -379,9 +375,7 @@ public class Policy {
|
||||
Assert.notNull(capabilities, "Capabilities must not be null");
|
||||
Assert.noNullElements(capabilities, "Capabilities must not contain null elements");
|
||||
|
||||
for (Capability capability : capabilities) {
|
||||
this.capabilities.add(capability);
|
||||
}
|
||||
this.capabilities.addAll(capabilities);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -611,180 +605,4 @@ public class Policy {
|
||||
|
||||
}
|
||||
|
||||
static class PolicySerializer extends JsonSerializer<Policy> {
|
||||
|
||||
@Override
|
||||
public void serialize(Policy value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
|
||||
gen.writeStartObject();
|
||||
|
||||
gen.writeFieldName("path");
|
||||
gen.writeStartObject();
|
||||
|
||||
for (Rule rule : value.getRules()) {
|
||||
gen.writeObjectField(rule.path, rule);
|
||||
}
|
||||
|
||||
gen.writeEndObject();
|
||||
gen.writeEndObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class PolicyDeserializer extends JsonDeserializer<Policy> {
|
||||
|
||||
@Override
|
||||
public Policy deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.getCurrentToken());
|
||||
|
||||
String fieldName = p.nextFieldName();
|
||||
|
||||
Set<Rule> rules = new LinkedHashSet<>();
|
||||
|
||||
if ("path".equals(fieldName)) {
|
||||
|
||||
p.nextToken();
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.getCurrentToken());
|
||||
|
||||
p.nextToken();
|
||||
|
||||
while (p.currentToken() == JsonToken.FIELD_NAME) {
|
||||
|
||||
String path = p.getCurrentName();
|
||||
p.nextToken();
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.getCurrentToken());
|
||||
|
||||
Rule rule = p.getCodec().readValue(p, Rule.class);
|
||||
rules.add(rule.withPath(path));
|
||||
|
||||
JsonToken jsonToken = p.nextToken();
|
||||
if (jsonToken == JsonToken.END_OBJECT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.END_OBJECT,
|
||||
"Expected END_OBJECT, got: " + p.getCurrentToken());
|
||||
p.nextToken();
|
||||
}
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.END_OBJECT,
|
||||
"Expected END_OBJECT, got: " + p.getCurrentToken());
|
||||
return Policy.of(rules);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class CapabilityToStringConverter implements Converter<Capability, String> {
|
||||
|
||||
@Override
|
||||
public String convert(Capability value) {
|
||||
return value.name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Capability.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class StringToCapabilityConverter implements Converter<String, Capability> {
|
||||
|
||||
@Override
|
||||
public Capability convert(String value) {
|
||||
|
||||
Capability capability = BuiltinCapabilities.find(value);
|
||||
|
||||
return capability != null ? capability : () -> value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Capability.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DurationToStringConverter implements Converter<Duration, String> {
|
||||
|
||||
@Override
|
||||
public String convert(Duration value) {
|
||||
return "" + value.getSeconds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Duration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class StringToDurationConverter implements Converter<String, Duration> {
|
||||
|
||||
static Pattern SECONDS = Pattern.compile("(\\d+)s");
|
||||
|
||||
static Pattern MINUTES = Pattern.compile("(\\d+)m");
|
||||
|
||||
static Pattern HOURS = Pattern.compile("(\\d+)h");
|
||||
|
||||
@Override
|
||||
public Duration convert(String value) {
|
||||
|
||||
try {
|
||||
return Duration.ofSeconds(Long.parseLong(value));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
|
||||
Matcher matcher = SECONDS.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofSeconds(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
matcher = MINUTES.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofMinutes(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
matcher = HOURS.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofHours(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported duration value: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Capability.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
import com.fasterxml.jackson.databind.util.Converter;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jackson 2 serializers and deserializers for {@link Policy}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 4.0
|
||||
*/
|
||||
class PolicyJackson2 {
|
||||
|
||||
static class PolicySerializer extends JsonSerializer<Policy> {
|
||||
|
||||
@Override
|
||||
public void serialize(Policy value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
|
||||
gen.writeStartObject();
|
||||
|
||||
gen.writeFieldName("path");
|
||||
gen.writeStartObject();
|
||||
|
||||
for (Policy.Rule rule : value.getRules()) {
|
||||
gen.writeObjectField(rule.getPath(), rule);
|
||||
}
|
||||
|
||||
gen.writeEndObject();
|
||||
gen.writeEndObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class PolicyDeserializer extends JsonDeserializer<Policy> {
|
||||
|
||||
@Override
|
||||
public Policy deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.getCurrentToken());
|
||||
|
||||
String fieldName = p.nextFieldName();
|
||||
|
||||
Set<Policy.Rule> rules = new LinkedHashSet<>();
|
||||
|
||||
if ("path".equals(fieldName)) {
|
||||
|
||||
p.nextToken();
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.getCurrentToken());
|
||||
|
||||
p.nextToken();
|
||||
|
||||
while (p.currentToken() == JsonToken.FIELD_NAME) {
|
||||
|
||||
String path = p.getCurrentName();
|
||||
p.nextToken();
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.getCurrentToken());
|
||||
|
||||
Policy.Rule rule = p.getCodec().readValue(p, Policy.Rule.class);
|
||||
rules.add(rule.withPath(path));
|
||||
|
||||
JsonToken jsonToken = p.nextToken();
|
||||
if (jsonToken == JsonToken.END_OBJECT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.END_OBJECT,
|
||||
"Expected END_OBJECT, got: " + p.getCurrentToken());
|
||||
p.nextToken();
|
||||
}
|
||||
|
||||
Assert.isTrue(p.getCurrentToken() == JsonToken.END_OBJECT,
|
||||
"Expected END_OBJECT, got: " + p.getCurrentToken());
|
||||
return Policy.of(rules);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class CapabilityToStringConverter implements Converter<Policy.Capability, String> {
|
||||
|
||||
@Override
|
||||
public String convert(Policy.Capability value) {
|
||||
return value.name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Policy.Capability.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class StringToCapabilityConverter implements Converter<String, Policy.Capability> {
|
||||
|
||||
@Override
|
||||
public Policy.Capability convert(String value) {
|
||||
|
||||
Policy.Capability capability = Policy.BuiltinCapabilities.find(value);
|
||||
|
||||
return capability != null ? capability : () -> value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Policy.Capability.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DurationToStringConverter implements Converter<Duration, String> {
|
||||
|
||||
@Override
|
||||
public String convert(Duration value) {
|
||||
return "" + value.getSeconds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Duration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class StringToDurationConverter implements Converter<String, Duration> {
|
||||
|
||||
static Pattern SECONDS = Pattern.compile("(\\d+)s");
|
||||
|
||||
static Pattern MINUTES = Pattern.compile("(\\d+)m");
|
||||
|
||||
static Pattern HOURS = Pattern.compile("(\\d+)h");
|
||||
|
||||
@Override
|
||||
public Duration convert(String value) {
|
||||
|
||||
try {
|
||||
return Duration.ofSeconds(Long.parseLong(value));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
|
||||
Matcher matcher = SECONDS.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofSeconds(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
matcher = MINUTES.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofMinutes(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
matcher = HOURS.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofHours(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported duration value: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Policy.Capability.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import tools.jackson.core.JsonGenerator;
|
||||
import tools.jackson.core.JsonParser;
|
||||
import tools.jackson.core.JsonToken;
|
||||
import tools.jackson.databind.DeserializationContext;
|
||||
import tools.jackson.databind.JavaType;
|
||||
import tools.jackson.databind.SerializationContext;
|
||||
import tools.jackson.databind.ValueDeserializer;
|
||||
import tools.jackson.databind.ValueSerializer;
|
||||
import tools.jackson.databind.type.TypeFactory;
|
||||
import tools.jackson.databind.util.Converter;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jackson 3 serializers and deserializers for {@link Policy}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 4.0
|
||||
*/
|
||||
class PolicyJackson3 {
|
||||
|
||||
static class PolicySerializer extends ValueSerializer<Policy> {
|
||||
|
||||
@Override
|
||||
public void serialize(Policy value, JsonGenerator gen, SerializationContext serializers) {
|
||||
|
||||
gen.writeStartObject();
|
||||
|
||||
gen.writeName("path");
|
||||
gen.writeStartObject();
|
||||
|
||||
for (Policy.Rule rule : value.getRules()) {
|
||||
gen.writePOJOProperty(rule.getPath(), rule);
|
||||
}
|
||||
|
||||
gen.writeEndObject();
|
||||
gen.writeEndObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class PolicyDeserializer extends ValueDeserializer<Policy> {
|
||||
|
||||
@Override
|
||||
public Policy deserialize(JsonParser p, DeserializationContext ctxt) {
|
||||
|
||||
Assert.isTrue(p.currentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.currentToken());
|
||||
|
||||
String fieldName = p.nextName();
|
||||
|
||||
Set<Policy.Rule> rules = new LinkedHashSet<>();
|
||||
|
||||
if ("path".equals(fieldName)) {
|
||||
|
||||
p.nextToken();
|
||||
Assert.isTrue(p.currentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.currentToken());
|
||||
|
||||
p.nextToken();
|
||||
|
||||
while (p.currentToken() == JsonToken.PROPERTY_NAME) {
|
||||
|
||||
String path = p.currentName();
|
||||
p.nextToken();
|
||||
|
||||
Assert.isTrue(p.currentToken() == JsonToken.START_OBJECT,
|
||||
"Expected START_OBJECT, got: " + p.currentToken());
|
||||
|
||||
Policy.Rule rule = p.objectReadContext().readValue(p, Policy.Rule.class);
|
||||
rules.add(rule.withPath(path));
|
||||
|
||||
JsonToken jsonToken = p.nextToken();
|
||||
if (jsonToken == JsonToken.END_OBJECT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.isTrue(p.currentToken() == JsonToken.END_OBJECT,
|
||||
"Expected END_OBJECT, got: " + p.currentToken());
|
||||
p.nextToken();
|
||||
}
|
||||
|
||||
Assert.isTrue(p.currentToken() == JsonToken.END_OBJECT, "Expected END_OBJECT, got: " + p.currentToken());
|
||||
return Policy.of(rules);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class CapabilityToStringConverter implements Converter<Policy.Capability, String> {
|
||||
|
||||
@Override
|
||||
public String convert(DeserializationContext ctxt, Policy.Capability value) {
|
||||
return value.name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convert(SerializationContext ctxt, Policy.Capability value) {
|
||||
return value.name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Policy.Capability.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class StringToCapabilityConverter implements Converter<String, Policy.Capability> {
|
||||
|
||||
@Override
|
||||
public Policy.Capability convert(DeserializationContext ctxt, String value) {
|
||||
return convert(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Policy.Capability convert(SerializationContext ctxt, String value) {
|
||||
return convert(value);
|
||||
}
|
||||
|
||||
public Policy.Capability convert(String value) {
|
||||
|
||||
Policy.Capability capability = Policy.BuiltinCapabilities.find(value);
|
||||
|
||||
return capability != null ? capability : () -> value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Policy.Capability.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DurationToStringConverter implements Converter<Duration, String> {
|
||||
|
||||
@Override
|
||||
public String convert(DeserializationContext ctxt, Duration value) {
|
||||
return convert(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convert(SerializationContext ctxt, Duration value) {
|
||||
return convert(value);
|
||||
}
|
||||
|
||||
public String convert(Duration value) {
|
||||
return "" + value.getSeconds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Duration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class StringToDurationConverter implements Converter<String, Duration> {
|
||||
|
||||
static Pattern SECONDS = Pattern.compile("(\\d+)s");
|
||||
|
||||
static Pattern MINUTES = Pattern.compile("(\\d+)m");
|
||||
|
||||
static Pattern HOURS = Pattern.compile("(\\d+)h");
|
||||
|
||||
@Override
|
||||
public Duration convert(DeserializationContext ctxt, String value) {
|
||||
return convert(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration convert(SerializationContext ctxt, String value) {
|
||||
return convert(value);
|
||||
}
|
||||
|
||||
public Duration convert(String value) {
|
||||
|
||||
try {
|
||||
return Duration.ofSeconds(Long.parseLong(value));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
|
||||
Matcher matcher = SECONDS.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofSeconds(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
matcher = MINUTES.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofMinutes(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
matcher = HOURS.matcher(value);
|
||||
if (matcher.matches()) {
|
||||
return Duration.ofHours(Long.parseLong(matcher.group(1)));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported duration value: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getInputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getOutputType(TypeFactory typeFactory) {
|
||||
return typeFactory.constructType(Policy.Capability.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,12 +15,15 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP PKI issue certificate API responses.
|
||||
*
|
||||
* @author Nanne Baars
|
||||
* @since 3.1
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class VaultIssuerCertificateRequestResponse extends VaultResponseSupport<Certificate> {
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.vault.support;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@@ -34,6 +35,7 @@ import org.springframework.util.Assert;
|
||||
* @author Maciej Drozdzowski
|
||||
* @see #builder()
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class VaultMount {
|
||||
|
||||
/**
|
||||
@@ -42,7 +44,7 @@ public class VaultMount {
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* Human readable description of the mount.
|
||||
* Human-readable description of the mount.
|
||||
*/
|
||||
@Nullable
|
||||
private final String description;
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP PKI issue certificate API responses.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class VaultSignCertificateRequestResponse extends VaultResponseSupport<Certificate> {
|
||||
|
||||
}
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Token API responses.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class VaultTokenResponse extends VaultResponse {
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.vault.authentication;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.vault.authentication;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
@@ -21,9 +21,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@@ -15,19 +15,18 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CertificateBundle}.
|
||||
@@ -160,14 +159,9 @@ class CertificateBundleUnitTests {
|
||||
|
||||
CertificateBundle loadCertificateBundle(String path) {
|
||||
|
||||
try {
|
||||
URL resource = getClass().getClassLoader().getResource(path);
|
||||
assertThat(resource).as("Resource " + path).isNotNull();
|
||||
return this.OBJECT_MAPPER.readValue(resource, CertificateBundle.class);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
URL resource = getClass().getClassLoader().getResource(path);
|
||||
assertThat(resource).as("Resource " + path).isNotNull();
|
||||
return this.OBJECT_MAPPER.readValue(resource, CertificateBundle.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.vault.support;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* {@link ObjectMapper} supplier for testing holding a singleton {@link ObjectMapper}
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.skyscreamer.jsonassert.JSONCompareMode;
|
||||
|
||||
@@ -12,7 +12,7 @@ xref:vault/propertysource.adoc[Vault Property Source] :: Mounting Vault Secret B
|
||||
|
||||
Mark Paluch
|
||||
|
||||
(C) 2008-2024 VMware, Inc.
|
||||
(C) 2008-2025 VMware, Inc.
|
||||
|
||||
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
|
||||
|
||||
|
||||
@@ -13,12 +13,23 @@ If you want to use Spring Vault in your project, declare a dependency to the `sp
|
||||
<artifactId>spring-vault-core</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-databind.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
====
|
||||
|
||||
The easiest way to find compatible versions of Spring Vault dependencies is by inspecting the properties section of link:https://github.com/spring-projects/spring-vault/blob/main/pom.xml[`spring-vault-parent`].
|
||||
We generally recommend upgrading to the latest dependency of Jackson, your HTTP clients and your Cloud provider SDK.
|
||||
We generally recommend upgrading to the latest dependency of Jackson 3, your HTTP clients and your Cloud provider SDK.
|
||||
|
||||
NOTE: Spring Vault 4.0 supports Jackson 3 and Jackson 2.
|
||||
Make sure to declare a Jackson dependency as Spring Vault does not include Jackson transitively for easier opt-in.
|
||||
When both Jackson 2 and Jackson 3 are on the classpath, Spring Vault will use Jackson 3 aligning with Spring Framework 7 preferences.
|
||||
Spring Vault also assumes the usage of Jackson 3 in the HTTP client.
|
||||
|
||||
[[dependencies.spring-framework]]
|
||||
== Spring Framework
|
||||
|
||||
Reference in New Issue
Block a user