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

Backport updates from main 2 #1909

Merged
merged 10 commits into from
Jul 9, 2024
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
27 changes: 20 additions & 7 deletions core/src/main/java/io/smallrye/openapi/runtime/io/JsonIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public static <V, A extends V, O extends V, AB, OB> JsonIO<V, A, O, AB, OB> newI
return jackson;
}

private boolean wrapped(String value, String prefix, String suffix) {
return value.startsWith(prefix) && value.endsWith(suffix);
}

default Object parseValue(String value) {
if (value == null || value.isEmpty()) {
return null;
Expand All @@ -42,10 +46,19 @@ default Object parseValue(String value) {
String trimmedValue = value.trim();

switch (trimmedValue.charAt(0)) {
case '{': /* JSON Object */
case '[': /* JSON Array */
case '-': /* JSON Negative Number */
case '0': /* JSON Numbers */
case '{':
case '[':
if (wrapped(trimmedValue, "{", "}") || wrapped(trimmedValue, "[", "]")) {
/* Looks like a JSON Object or Array */
try {
return fromJson(fromString(trimmedValue, Format.JSON));
} catch (Exception e) {
IoLogging.logger.unparseableJson(trimmedValue);
}
}
break;
case '-': /* Negative Number */
case '0': /* Numbers */
case '1':
case '2':
case '3':
Expand All @@ -56,11 +69,11 @@ default Object parseValue(String value) {
case '8':
case '9':
try {
return fromJson(fromString(trimmedValue, Format.JSON));
} catch (Exception e) {
return new BigDecimal(trimmedValue);
} catch (NumberFormatException e) {
IoLogging.logger.unparseableJson(trimmedValue);
break;
}
break;
case 't':
return "true".equals(trimmedValue) ? Boolean.TRUE : value;
case 'f':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -763,4 +763,30 @@ public String getWo() {

assertJsonEquals("components.schemas.jackson-property-access.json", Bean.class);
}

@Test
void testExceptionalExampleParsing() throws IOException, JSONException {
@Schema(name = "Bean")
class Bean {
@Schema(example = "{ Looks like object, but invalid }")
public Object property1;
@Schema(example = "{ \"key\": \"object end missing\"")
public Object property2;
@Schema(example = "[ Looks like array, but invalid ]")
public Object property3;
@Schema(example = "[ \"array end missing\"")
public Object property4;
@Schema(example = "trick") // not Boolean.TRUE
public Object property5;
@Schema(example = "fake") // not Boolean.FALSE
public Object property6;
@Schema(example = "1046\n1049\n1051") // not a number
public Object property7;
@Schema(example = "") // empty
public Object property8;

}

assertJsonEquals("components.schemas.exceptional-examples.json", Bean.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"openapi" : "3.1.0",
"components" : {
"schemas" : {
"Bean" : {
"type" : "object",
"properties" : {
"property1" : {
"examples" : [ "{ Looks like object, but invalid }" ]
},
"property2" : {
"examples" : [ "{ \"key\": \"object end missing\"" ]
},
"property3" : {
"examples" : [ "[ Looks like array, but invalid ]" ]
},
"property4" : {
"examples" : [ "[ \"array end missing\"" ]
},
"property5" : {
"examples" : [ "trick" ]
},
"property6" : {
"examples" : [ "fake" ]
},
"property7" : {
"examples" : [ "1046\n1049\n1051" ]
},
"property8" : {
"examples" : [ "" ]
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,36 @@ private void processResourceClasses(OpenAPI openApi) {
TypeResolver resolver = TypeResolver.forClass(context, resourceClass, null);
context.getResolverStack().push(resolver);
// Process tags (both declarations and references).
Set<String> tags = processTags(context, resourceClass, openApi, false);
Set<String> tags = processResourceClassTags(openApi, resourceClass);
processResourceClass(openApi, resourceClass, null, tags);
context.getResolverStack().pop();
}
}

/**
* Find Tag annotations on the resource class or any super type. Stop searching the
* class hierarchy when any Tags are found
*
* @param openApi
* @param resourceClass
* @return set of tag names found on the resourceClass or inherited from a super type
*/
private Set<String> processResourceClassTags(OpenAPI openApi, ClassInfo resourceClass) {
Set<String> tags = null;

while ((tags = processTags(context, resourceClass, openApi, true)) == null) {
Type superType = resourceClass.superClassType();
resourceClass = superType != null ? context.getAugmentedIndex().getClass(superType) : null;

if (resourceClass == null) {
tags = Collections.emptySet();
break;
}
}

return tags;
}

/**
* Processing a single JAX-RS resource class (annotated with @Path).
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.smallrye.openapi.runtime.scanner;

import java.io.IOException;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import org.json.JSONException;
import org.junit.jupiter.api.Test;

class TagInheritanceTest extends IndexScannerTestBase {

private static void test(String expectedResource, Class<?>... classes) throws IOException, JSONException {
OpenAPI result = scan(classes);
assertJsonEquals(expectedResource, result);
}

@Test
void testTagInherited() throws IOException, JSONException {
@Tag(name = "qux", description = "ignored")
abstract class RootResource {
}

@Tag(name = "foobar", description = "baz")
abstract class BaseResource extends RootResource {
@GET
@Path("ping")
@Produces(MediaType.TEXT_PLAIN)
@Operation(summary = "Bla")
public String ping() {
return "ping";
}
}

@Path("/foobar")
class MyResource extends BaseResource {
@GET
@Path("pong")
@Produces(MediaType.TEXT_PLAIN)
@Operation(summary = "Bla")
public String pong() {
return "pong";
}
}

test("resource.tags.inherited.json", RootResource.class, BaseResource.class, MyResource.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"openapi" : "3.1.0",
"tags" : [ {
"name" : "foobar",
"description" : "baz"
} ],
"paths" : {
"/foobar/ping" : {
"get" : {
"tags" : [ "foobar" ],
"summary" : "Bla",
"responses" : {
"200" : {
"description" : "OK",
"content" : {
"text/plain" : {
"schema" : {
"type" : "string"
}
}
}
}
}
}
},
"/foobar/pong" : {
"get" : {
"tags" : [ "foobar" ],
"summary" : "Bla",
"responses" : {
"200" : {
"description" : "OK",
"content" : {
"text/plain" : {
"schema" : {
"type" : "string"
}
}
}
}
}
}
}
}
}
12 changes: 6 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-parent</artifactId>
<version>44</version>
<version>45</version>
</parent>

<artifactId>smallrye-open-api-parent</artifactId>
Expand All @@ -18,20 +18,20 @@

<properties>
<version.buildhelper.plugin>3.6.0</version.buildhelper.plugin>
<jackson-bom.version>2.17.1</jackson-bom.version>
<jackson-bom.version>2.17.2</jackson-bom.version>
<version.eclipse.microprofile.config>3.0.3</version.eclipse.microprofile.config>
<version.io.smallrye.jandex>3.2.0</version.io.smallrye.jandex>
<version.io.smallrye.smallrye-config>3.8.3</version.io.smallrye.smallrye-config>
<version.eclipse.microprofile.openapi>4.0</version.eclipse.microprofile.openapi>
<version.org.hamcrest>1.3</version.org.hamcrest>
<version.org.hamcrest.java-hamcrest>2.0.0.0</version.org.hamcrest.java-hamcrest>
<version.org.skyscreamer>1.5.1</version.org.skyscreamer>
<version.org.skyscreamer>1.5.3</version.org.skyscreamer>
<version.maven-resources-plugin>3.3.1</version.maven-resources-plugin>
<version.com.github.eirslett.frontend-maven-plugin>1.15.0</version.com.github.eirslett.frontend-maven-plugin>
<version.quarkus>3.12.0</version.quarkus>
<version.quarkus>3.12.1</version.quarkus>
<version.testng>7.10.2</version.testng>
<version.arquillian.jetty>2.0.0.Final</version.arquillian.jetty>
<version.jetty>11.0.21</version.jetty>
<version.jetty>11.0.22</version.jetty>

<!-- Use Jakarta EE 10 versions -->
<version.resteasy>6.2.3.Final</version.resteasy>
Expand Down Expand Up @@ -450,7 +450,7 @@
</activation>
<properties>
<jboss.extra.opts>--add-modules java.se</jboss.extra.opts>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.release>11</maven.compiler.release>
</properties>
</profile>
</profiles>
Expand Down
6 changes: 3 additions & 3 deletions testsuite/data/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-build-parent</artifactId>
<version>44</version>
<version>45</version>
<relativePath />
</parent>

Expand All @@ -21,7 +21,7 @@
<maven.compiler.release>${java.version}</maven.compiler.release>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
<quarkus.platform.version>3.12.0</quarkus.platform.version>
<quarkus.platform.version>3.12.1</quarkus.platform.version>
<quarkus.package.type>uber-jar</quarkus.package.type>
<quarkus.package.add-runner-suffix>false</quarkus.package.add-runner-suffix>
</properties>
Expand Down Expand Up @@ -108,7 +108,7 @@
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<version>1.5.1</version>
<version>1.5.3</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
2 changes: 1 addition & 1 deletion testsuite/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</modules>

<properties>
<version.org.jboss.arquillian>1.8.0.Final</version.org.jboss.arquillian>
<version.org.jboss.arquillian>1.8.1.Final</version.org.jboss.arquillian>
</properties>

<dependencyManagement>
Expand Down
1 change: 1 addition & 0 deletions tools/maven-plugin/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ E.g. for includeDependenciesScopes could be configured as:
- `skip` (boolean, default: false) - Skip execution of the plugin.
- `encoding` (String) - Encoding of output OpenAPI files.
- `outputFileTypeFilter` (String, default: ALL) - Set this to `YAML` in order to let the generation process produce just *.yaml output, `JSON` to obtain *.json files only. The default is `ALL`, which will generate both file types.
- `scanners` (List<String>) - Names of the AnnotationScanner implementations that should be executed. If omitted or an empty list, all scanners will be executed. The names of the scanners available by default are `JAX-RS`, `Spring`, and `Vert.x`.

== MicroProfile OpenAPI Properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ public class GenerateSchemaMojo extends AbstractMojo {
@Parameter(property = "configProperties")
private File configProperties;

/**
* Configuration property to specify the list of scanners to use. If the list is empty the default scanners are used.
*/
@Parameter(property = "scanners")
private List<String> scanners;

// Properies as per OpenAPI Config.

/**
Expand Down Expand Up @@ -298,6 +304,7 @@ private SmallRyeOpenAPI generateOpenAPI(IndexView index) throws IOException, Dep
.withConfig(config)
.withApplicationClassLoader(getClassLoader())
.withIndex(index)
.withScannerFilter(scanners != null && !scanners.isEmpty() ? x -> scanners.contains(x) : x -> true)
.build();
}

Expand Down