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

Change the OpenAPI config mapping to use Config Interceptors #18936

Merged
merged 1 commit into from
Jul 23, 2021
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
@@ -0,0 +1,89 @@
package io.quarkus.smallrye.openapi.deployment;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import io.quarkus.runtime.configuration.HyphenateEnumConverter;
import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.RelocateConfigSourceInterceptor;
import io.smallrye.openapi.api.OpenApiConfig;

/**
* Maps config from MicroProfile and SmallRye to Quarkus
*/
public class OpenApiConfigMapping extends RelocateConfigSourceInterceptor {
private static final Map<String, String> RELOCATIONS = relocations();
private final HyphenateEnumConverter enumConverter = new HyphenateEnumConverter(OpenApiConfig.OperationIdStrategy.class);

public OpenApiConfigMapping() {
super(RELOCATIONS);
}

@Override
public ConfigValue getValue(ConfigSourceInterceptorContext context, String name) {
ConfigValue configValue = super.getValue(context, name);
// Special case for enum. The converter run after the interceptors, so we have to do this here.
if (name.equals(io.smallrye.openapi.api.constants.OpenApiConstants.OPERATION_ID_STRAGEGY)) {
if (configValue != null) {
String correctValue = enumConverter.convert(configValue.getValue()).toString();
configValue = configValue.withValue(correctValue);
}
}
return configValue;
}

@Override
public Iterator<String> iterateNames(final ConfigSourceInterceptorContext context) {
final Set<String> names = new HashSet<>();
final Iterator<String> namesIterator = context.iterateNames();
while (namesIterator.hasNext()) {
final String name = namesIterator.next();
names.add(name);
final String mappedName = RELOCATIONS.get(name);
if (mappedName != null) {
names.add(mappedName);
}
}
return names.iterator();
}

private static Map<String, String> relocations() {
Map<String, String> relocations = new HashMap<>();
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.OPEN_API_VERSION, QUARKUS_OPEN_API_VERSION);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_TITLE, QUARKUS_INFO_TITLE);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_VERSION, QUARKUS_INFO_VERSION);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_DESCRIPTION, QUARKUS_INFO_DESCRIPTION);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_TERMS, QUARKUS_INFO_TERMS);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_CONTACT_EMAIL, QUARKUS_INFO_CONTACT_EMAIL);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_CONTACT_NAME, QUARKUS_INFO_CONTACT_NAME);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_CONTACT_URL, QUARKUS_INFO_CONTACT_URL);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_LICENSE_NAME, QUARKUS_INFO_LICENSE_NAME);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.INFO_LICENSE_URL, QUARKUS_INFO_LICENSE_URL);
mapKey(relocations, io.smallrye.openapi.api.constants.OpenApiConstants.OPERATION_ID_STRAGEGY,
QUARKUS_OPERATION_ID_STRAGEGY);
return Collections.unmodifiableMap(relocations);
}

private static void mapKey(Map<String, String> map, String quarkusKey, String otherKey) {
map.put(quarkusKey, otherKey);
map.put(otherKey, quarkusKey);
}

private static final String QUARKUS_OPEN_API_VERSION = "quarkus.smallrye-openapi.open-api-version";
private static final String QUARKUS_INFO_TITLE = "quarkus.smallrye-openapi.info-title";
private static final String QUARKUS_INFO_VERSION = "quarkus.smallrye-openapi.info-version";
private static final String QUARKUS_INFO_DESCRIPTION = "quarkus.smallrye-openapi.info-description";
private static final String QUARKUS_INFO_TERMS = "quarkus.smallrye-openapi.info-terms-of-service";
private static final String QUARKUS_INFO_CONTACT_EMAIL = "quarkus.smallrye-openapi.info-contact-email";
private static final String QUARKUS_INFO_CONTACT_NAME = "quarkus.smallrye-openapi.info-contact-name";
private static final String QUARKUS_INFO_CONTACT_URL = "quarkus.smallrye-openapi.info-contact-url";
private static final String QUARKUS_INFO_LICENSE_NAME = "quarkus.smallrye-openapi.info-license-name";
private static final String QUARKUS_INFO_LICENSE_URL = "quarkus.smallrye-openapi.info-license-url";
private static final String QUARKUS_OPERATION_ID_STRAGEGY = "quarkus.smallrye-openapi.operation-id-strategy";

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.logging.LogCleanupFilterBuildItem;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.resteasy.common.spi.ResteasyDotNames;
Expand Down Expand Up @@ -121,58 +121,6 @@ public class SmallRyeOpenApiProcessor {
System.setProperty(io.smallrye.openapi.api.constants.OpenApiConstants.DEFAULT_CONSUMES, "application/json");
}

@BuildStep
void mapConfig(SmallRyeOpenApiConfig openApiConfig,
BuildProducer<SystemPropertyBuildItem> systemProperties) {

if (openApiConfig.openApiVersion.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(
io.smallrye.openapi.api.constants.OpenApiConstants.OPEN_API_VERSION, openApiConfig.openApiVersion.get()));
}
if (openApiConfig.infoTitle.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(io.smallrye.openapi.api.constants.OpenApiConstants.INFO_TITLE,
openApiConfig.infoTitle.get()));
}
if (openApiConfig.infoVersion.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(
io.smallrye.openapi.api.constants.OpenApiConstants.INFO_VERSION, openApiConfig.infoVersion.get()));
}
if (openApiConfig.infoDescription.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(
io.smallrye.openapi.api.constants.OpenApiConstants.INFO_DESCRIPTION, openApiConfig.infoDescription.get()));
}
if (openApiConfig.infoTermsOfService.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(io.smallrye.openapi.api.constants.OpenApiConstants.INFO_TERMS,
openApiConfig.infoTermsOfService.get()));
}
if (openApiConfig.infoContactEmail.isPresent()) {
systemProperties
.produce(new SystemPropertyBuildItem(io.smallrye.openapi.api.constants.OpenApiConstants.INFO_CONTACT_EMAIL,
openApiConfig.infoContactEmail.get()));
}
if (openApiConfig.infoContactName.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(
io.smallrye.openapi.api.constants.OpenApiConstants.INFO_CONTACT_NAME, openApiConfig.infoContactName.get()));
}
if (openApiConfig.infoContactUrl.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(
io.smallrye.openapi.api.constants.OpenApiConstants.INFO_CONTACT_URL, openApiConfig.infoContactUrl.get()));
}
if (openApiConfig.infoLicenseName.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(
io.smallrye.openapi.api.constants.OpenApiConstants.INFO_LICENSE_NAME, openApiConfig.infoLicenseName.get()));
}
if (openApiConfig.infoLicenseUrl.isPresent()) {
systemProperties.produce(new SystemPropertyBuildItem(
io.smallrye.openapi.api.constants.OpenApiConstants.INFO_LICENSE_URL, openApiConfig.infoLicenseUrl.get()));
}
if (openApiConfig.operationIdStrategy.isPresent()) {
systemProperties.produce(
new SystemPropertyBuildItem(io.smallrye.openapi.api.constants.OpenApiConstants.OPERATION_ID_STRAGEGY,
openApiConfig.operationIdStrategy.get().name()));
}
}

@BuildStep
void contributeClassesToIndex(BuildProducer<AdditionalIndexedClassesBuildItem> additionalIndexedClasses) {
// contribute additional JDK classes to the index, because SmallRye OpenAPI will check if some
Expand All @@ -185,6 +133,12 @@ void contributeClassesToIndex(BuildProducer<AdditionalIndexedClassesBuildItem> a
Object.class.getName()));
}

@BuildStep
void registerNativeImageResources(BuildProducer<ServiceProviderBuildItem> serviceProvider) throws IOException {
// To map from smallrye and mp config to quarkus
serviceProvider.produce(ServiceProviderBuildItem.allProvidersFromClassPath(OpenApiConfigMapping.class.getName()));
}

@BuildStep
List<HotDeploymentWatchedFileBuildItem> configFiles() {
return Stream.of(META_INF_OPENAPI_YAML, WEB_INF_CLASSES_META_INF_OPENAPI_YAML,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.smallrye.openapi.deployment.OpenApiConfigMapping
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.quarkus.smallrye.openapi.test.jaxrs;

import org.hamcrest.Matchers;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class ConfigMappingTest {
private static final String OPEN_API_PATH = "/q/openapi";

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(DefaultContentTypeResource.class, Greeting.class)

.addAsResource(new StringAsset("quarkus.smallrye-openapi.open-api-version=3.0.3\n"
+ "quarkus.smallrye-openapi.info-title=My API\n"
+ "quarkus.smallrye-openapi.info-version=1.2.3\n"
+ "quarkus.smallrye-openapi.info-description=My Description\n"
+ "quarkus.smallrye-openapi.info-terms-of-service=Some terms\n"
+ "quarkus.smallrye-openapi.info-contact-email=my.email@provider.com\n"
+ "quarkus.smallrye-openapi.info-contact-name=My Name\n"
+ "quarkus.smallrye-openapi.info-contact-url=http:\\//www.foo.bar\n"
+ "quarkus.smallrye-openapi.info-license-name=Some License\n"
+ "quarkus.smallrye-openapi.info-license-url=http:\\//www.somelicense.com\n"
+ "quarkus.smallrye-openapi.operation-id-strategy=package-class-method"),
"application.properties"));

@Test
public void testOpenApiPathAccessResource() {
RestAssured.given().queryParam("format", "JSON")
.when().get(OPEN_API_PATH)
.then()
.log().body().and()
.body("openapi",
Matchers.equalTo("3.0.3"))
.body("info.title",
Matchers.equalTo("My API"))
.body("info.description",
Matchers.equalTo("My Description"))
.body("info.termsOfService",
Matchers.equalTo("Some terms"))
.body("info.contact.name",
Matchers.equalTo("My Name"))
.body("info.contact.url",
Matchers.equalTo("http://www.foo.bar"))
.body("info.contact.email",
Matchers.equalTo("[email protected]"))
.body("info.license.name",
Matchers.equalTo("Some License"))
.body("info.license.url",
Matchers.equalTo("http://www.somelicense.com"))
.body("info.version",
Matchers.equalTo("1.2.3"))
.body("paths.'/greeting/goodbye'.get.operationId",
Matchers.equalTo("io.quarkus.smallrye.openapi.test.jaxrs.DefaultContentTypeResource_byebye"));

}
}