Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Adapt to SnakeYAML 2.0 changes #5793

Merged
merged 12 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
* Copyright (c) 2022, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,6 +39,7 @@
import io.helidon.config.MutabilitySupport;

import org.eclipse.microprofile.config.spi.ConfigSource;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;

Expand Down Expand Up @@ -380,7 +381,7 @@ public String getName() {
static Map toMap(Reader reader) {
// the default of Snake YAML is a Map, safe constructor makes sure we never deserialize into anything
// harmful
Yaml yaml = new Yaml(new SafeConstructor());
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
barchetta marked this conversation as resolved.
Show resolved Hide resolved
return (Map) yaml.loadAs(reader, Object.class);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021 Oracle and/or its affiliates.
* Copyright (c) 2020, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,7 @@
import io.helidon.config.spi.ConfigParserException;

import jakarta.annotation.Priority;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;

Expand Down Expand Up @@ -113,7 +114,7 @@ public ObjectNode parse(Content content) throws ConfigParserException {
static Map toMap(Reader reader) {
// the default of Snake YAML is a Map, safe constructor makes sure we never deserialize into anything
// harmful
Yaml yaml = new Yaml(new SafeConstructor());
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
return (Map) yaml.loadAs(reader, Object.class);
}

Expand Down
2 changes: 1 addition & 1 deletion dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
<version.lib.prometheus>0.9.0</version.lib.prometheus>
<version.lib.slf4j>1.7.32</version.lib.slf4j>
<version.lib.smallrye-openapi>2.1.16</version.lib.smallrye-openapi>
<version.lib.snakeyaml>1.32</version.lib.snakeyaml>
<version.lib.snakeyaml>2.0</version.lib.snakeyaml>
<version.lib.typesafe-config>1.4.2</version.lib.typesafe-config>
<version.lib.tyrus>2.0.4</version.lib.tyrus>
<version.lib.weld-api>4.0.SP1</version.lib.weld-api>
Expand Down
6 changes: 6 additions & 0 deletions examples/todo-app/backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<version.datastax.driver.core>4.9.0</version.datastax.driver.core>
<version.datastax.driver.query.builder>4.9.0</version.datastax.driver.query.builder>
<version.codahale.metrics.core>3.0.2</version.codahale.metrics.core>
<version.lib.snakeyaml.override>1.32</version.lib.snakeyaml.override>
</properties>

<dependencyManagement>
Expand All @@ -57,6 +58,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${version.lib.snakeyaml.override}</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
16 changes: 16 additions & 0 deletions microprofile/tests/tck/tck-openapi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@
<artifactId>tck-openapi</artifactId>
<name>Helidon Microprofile Tests TCK OpenAPI</name>

<properties>
<selectedSnakeYamlVersion>1.32</selectedSnakeYamlVersion>
</properties>

<!-- The TCK uses Jackson which in turn uses SnakeYAML APIs that have disappeared in 2.0. So, for running the TCK
use the earlier SnakeYAML release (until an updated Jackson release becomes available). -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${selectedSnakeYamlVersion}</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.helidon.microprofile.tests</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021 Oracle and/or its affiliates.
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,6 +30,7 @@
import org.eclipse.microprofile.openapi.models.responses.APIResponse;
import org.eclipse.microprofile.openapi.models.responses.APIResponses;
import org.eclipse.microprofile.openapi.models.security.SecurityRequirement;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.Mark;
Expand Down Expand Up @@ -149,7 +150,7 @@ record ChildMapType<P, C>(Class<P> parentType,
Function<Class<?>, ExpandedTypeDescription.MapLikeTypeDescription<P, C>> typeDescriptionFactory) { }

/**
* Type information about a map-resembling interface in which a child can have 0, 1, or more values i.e., the child is
* Type information about a map-resembling interface in which a child can have 0, 1, or more values (i.e., the child is
* a list).
*
* @param <P> parent type
Expand All @@ -166,7 +167,7 @@ record ChildMapListType<P, C>(
private static final Logger LOGGER = Logger.getLogger(CustomConstructor.class.getName());

CustomConstructor(TypeDescription td) {
super(td);
super(td, new LoaderOptions());
yamlClassConstructors.put(NodeId.mapping, new ConstructMapping());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021 Oracle and/or its affiliates.
* Copyright (c) 2020, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -61,46 +61,18 @@ public Tag getTag() {
return delegate.getTag();
}

@Override
public void setTag(Tag tag) {
delegate.setTag(tag);
}

@Override
public void setTag(String tag) {
delegate.setTag(tag);
}

@Override
@Deprecated
public void putListPropertyType(String property, Class<?> type) {
delegate.putListPropertyType(property, type);
}

@Override
@Deprecated
public Class<? extends Object> getListPropertyType(String property) {
return delegate.getListPropertyType(property);
}

@Override
@Deprecated
public void putMapPropertyType(String property, Class<?> key, Class<?> value) {
delegate.putMapPropertyType(property, key, value);
}

@Override
@Deprecated
public Class<? extends Object> getMapKeyType(String property) {
return delegate.getMapKeyType(property);
}

@Override
@Deprecated
public Class<? extends Object> getMapValueType(String property) {
return delegate.getMapValueType(property);
}

@Override
public void addPropertyParameters(String pName, Class<?>... classes) {
delegate.addPropertyParameters(pName, classes);
Expand Down
13 changes: 12 additions & 1 deletion openapi/src/main/java/io/helidon/openapi/OpenAPISupport.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022 Oracle and/or its affiliates.
* Copyright (c) 2020, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -86,6 +86,7 @@
import org.jboss.jandex.IndexView;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.introspector.PropertySubstitute;

import static io.helidon.webserver.cors.CorsEnabledServiceHelper.CORS_CONFIG_KEY;

Expand Down Expand Up @@ -148,6 +149,11 @@ MediaType mediaType() {

private static final JsonReaderFactory JSON_READER_FACTORY = Json.createReaderFactory(Collections.emptyMap());

// As a static we keep a reference to the logger, thereby making sure any changes we make are persistent. (JUL holds
// only weak references to loggers internally.)
private static final Logger SNAKE_YAML_INTROSPECTOR_LOGGER =
Logger.getLogger(PropertySubstitute.class.getPackage().getName());

/**
* The SnakeYAMLParserHelper is generated by a maven plug-in.
*/
Expand Down Expand Up @@ -262,6 +268,11 @@ private void registerJsonpSupport(ServerRequest req, ServerResponse res) {
static SnakeYAMLParserHelper<ExpandedTypeDescription> helper() {
return access(HELPER_ACCESS, () -> {
if (helper == null) {
Config config = Config.create();
boolean allowSnakeYamlWarnings = (config.get("openapi.parsing.warnings.enabled").asBoolean().orElse(false));
if (SNAKE_YAML_INTROSPECTOR_LOGGER.isLoggable(Level.WARNING) && !allowSnakeYamlWarnings) {
SNAKE_YAML_INTROSPECTOR_LOGGER.setLevel(Level.SEVERE);
}
helper = SnakeYAMLParserHelper.create(ExpandedTypeDescription::create);
adjustTypeDescriptions(helper.types());
}
Expand Down
5 changes: 2 additions & 3 deletions openapi/src/main/java/io/helidon/openapi/Serializer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021 Oracle and/or its affiliates.
* Copyright (c) 2020, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -103,16 +103,15 @@ static class CustomRepresenter extends Representer {

private static final String EXTENSIONS = "extensions";

private final DumperOptions dumperOptions;
private final DumperOptions.ScalarStyle stringStyle;

private final Map<Class<?>, ExpandedTypeDescription> implsToTypes;

CustomRepresenter(Map<Class<?>, ExpandedTypeDescription> types,
Map<Class<?>, ExpandedTypeDescription> implsToTypes, DumperOptions dumperOptions,
DumperOptions.ScalarStyle stringStyle) {
super(dumperOptions);
this.implsToTypes = implsToTypes;
this.dumperOptions = dumperOptions;
this.stringStyle = stringStyle;
types.values().stream()
.map(ImplTypeDescription::new)
Expand Down
1 change: 1 addition & 0 deletions tests/integration/gh-5792/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/*
20 changes: 20 additions & 0 deletions tests/integration/gh-5792/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# helidon-tests-integration-yaml-parsing

Sample Helidon SE project to make sure that we can build and run using an older release of SnakeYAML in case users need to fall back.

Note that the static OpenAPI document packaged into the application JAR file intentionally _does not_ describe the API for this service.
It contains a much richer definition to exercise YAML parsing a bit more.

## Build and run

With JDK17+
```bash
mvn package
java -jar target/helidon-tests-integration-yaml-parsing.jar
```

## Try OpenAPI

```
curl -s -X GET http://localhost:8080/openapi

105 changes: 105 additions & 0 deletions tests/integration/gh-5792/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2023 Oracle and/or its affiliates.

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

http://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.
-->
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.helidon.applications</groupId>
<artifactId>helidon-se</artifactId>
<version>3.1.3-SNAPSHOT</version>
<relativePath>../../../applications/se/pom.xml</relativePath>
</parent>
<groupId>io.helidon.tests.integration</groupId>
<artifactId>helidon-tests-integration-yaml-parsing</artifactId>
<version>3.1.3-SNAPSHOT</version>

<properties>
<mainClass>io.helidon.tests.integration.yamlparsing.Main</mainClass>
<selectedSnakeYamlVersion>1.32</selectedSnakeYamlVersion>
</properties>

<dependencyManagement>
<dependencies>
<!-- Verify that the app builds correctly and that config and OpenAPI document YAML parsing work with the older
SnakeYAML release. -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${selectedSnakeYamlVersion}</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.helidon.webserver</groupId>
<artifactId>helidon-webserver</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.media</groupId>
<artifactId>helidon-media-jsonp</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.openapi</groupId>
<artifactId>helidon-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.webclient</groupId>
<artifactId>helidon-webclient</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<selected-snakeyaml-version>${selectedSnakeYamlVersion}</selected-snakeyaml-version>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-libs</id>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading