From d1d990acd7a06aa34112896d753bcae679203f35 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 28 Feb 2023 09:39:43 +0000 Subject: [PATCH 1/2] Improve compatibility with SnakeYAML 2.0 Closes gh-35414 --- .../boot/env/OriginTrackedYamlLoader.java | 39 +++++++++++++++++-- ...lPropertySourceLoaderSnakeYaml20Tests.java | 29 ++++++++++++++ src/checkstyle/checkstyle-suppressions.xml | 1 + 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderSnakeYaml20Tests.java diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedYamlLoader.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedYamlLoader.java index 16861bac0b..4051044b7c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedYamlLoader.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedYamlLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2023 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. @@ -16,6 +16,9 @@ package org.springframework.boot.env; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -45,6 +48,7 @@ import org.springframework.boot.origin.OriginTrackedValue; import org.springframework.boot.origin.TextResourceOrigin; import org.springframework.boot.origin.TextResourceOrigin.Location; import org.springframework.core.io.Resource; +import org.springframework.util.ReflectionUtils; /** * Class to load {@code .yml} files into a map of {@code String} to @@ -73,8 +77,8 @@ class OriginTrackedYamlLoader extends YamlProcessor { private Yaml createYaml(LoaderOptions loaderOptions) { BaseConstructor constructor = new OriginTrackingConstructor(loaderOptions); - Representer representer = new Representer(); DumperOptions dumperOptions = new DumperOptions(); + Representer representer = new Representer(dumperOptions); LimitedResolver resolver = new LimitedResolver(); return new Yaml(constructor, representer, dumperOptions, loaderOptions, resolver); } @@ -167,7 +171,12 @@ class OriginTrackedYamlLoader extends YamlProcessor { /** * {@link Resolver} that limits {@link Tag#TIMESTAMP} tags. */ - private static class LimitedResolver extends Resolver { + static class LimitedResolver extends Resolver { + + private static final MethodType SNAKE_YAML_2_ADD_IMPLICIT_RESOLVER_METHOD_TYPE = MethodType + .methodType(void.class, Tag.class, Pattern.class, String.class, int.class); + + private volatile MethodHandle snakeYaml2ImplicitResolverMethod; @Override public void addImplicitResolver(Tag tag, Pattern regexp, String first) { @@ -177,6 +186,30 @@ class OriginTrackedYamlLoader extends YamlProcessor { super.addImplicitResolver(tag, regexp, first); } + public void addImplicitResolver(Tag tag, Pattern regexp, String first, int limit) { + // Support for SnakeYAML 2.0 + if (tag == Tag.TIMESTAMP) { + return; + } + try { + getSnakeYaml2ImplicitResolverMethod().invoke(this, tag, regexp, first, limit); + } + catch (Throwable ex) { + ReflectionUtils.rethrowRuntimeException(ex); + } + } + + private MethodHandle getSnakeYaml2ImplicitResolverMethod() + throws NoSuchMethodException, IllegalAccessException { + MethodHandle snakeYaml2ImplicitResolverMethod = this.snakeYaml2ImplicitResolverMethod; + if (snakeYaml2ImplicitResolverMethod == null) { + snakeYaml2ImplicitResolverMethod = MethodHandles.lookup().findSpecial(Resolver.class, + "addImplicitResolver", SNAKE_YAML_2_ADD_IMPLICIT_RESOLVER_METHOD_TYPE, getClass()); + this.snakeYaml2ImplicitResolverMethod = snakeYaml2ImplicitResolverMethod; + } + return snakeYaml2ImplicitResolverMethod; + } + } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderSnakeYaml20Tests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderSnakeYaml20Tests.java new file mode 100644 index 0000000000..6844401765 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderSnakeYaml20Tests.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2023 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.boot.env; + +import org.springframework.boot.testsupport.classpath.ClassPathOverrides; + +/** + * Tests for {@link YamlPropertySourceLoader} with SnakeYAML 2.0. + * + * @author Andy Wilkinson + */ +@ClassPathOverrides("org.yaml:snakeyaml:2.0") +class YamlPropertySourceLoaderSnakeYaml20Tests extends YamlPropertySourceLoaderTests { + +} diff --git a/src/checkstyle/checkstyle-suppressions.xml b/src/checkstyle/checkstyle-suppressions.xml index 2547fa96e3..44859cc43b 100644 --- a/src/checkstyle/checkstyle-suppressions.xml +++ b/src/checkstyle/checkstyle-suppressions.xml @@ -54,4 +54,5 @@ + From ef1401fcc9f5bfc21f05b2beb2cb6e83698c1373 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 12 May 2023 14:20:40 -0700 Subject: [PATCH 2/2] Fix formatting --- .../CloudFoundryWebEndpointServletHandlerMapping.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java index d6f2cf0b78..ddb9c44714 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java @@ -94,7 +94,7 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin @ResponseBody public Map> links(HttpServletRequest request, HttpServletResponse response) { SecurityResponse securityResponse = CloudFoundryWebEndpointServletHandlerMapping.this.securityInterceptor - .preHandle(request, null); + .preHandle(request, null); if (!securityResponse.getStatus().equals(HttpStatus.OK)) { sendFailureResponse(response, securityResponse); } @@ -104,11 +104,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin return Collections.singletonMap("_links", filteredLinks); } Map links = CloudFoundryWebEndpointServletHandlerMapping.this.linksResolver - .resolveLinks(request.getRequestURL().toString()); - filteredLinks = links.entrySet() - .stream() - .filter((e) -> e.getKey().equals("self") || accessLevel.isAccessAllowed(e.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + .resolveLinks(request.getRequestURL().toString()); + filteredLinks = links.entrySet().stream() + .filter((e) -> e.getKey().equals("self") || accessLevel.isAccessAllowed(e.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); return Collections.singletonMap("_links", filteredLinks); }