Skip to content
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
2 changes: 1 addition & 1 deletion docs-examples/example-kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ dependencies {
testImplementation(mn.micronaut.hibernate.validator)
testImplementation(libs.kotlin.stdlib.jdk8)
testImplementation(libs.kotlin.reflect)
testImplementation(libs.kotlintest.runner.junit5)

testRuntimeOnly(libs.logback.classic)
testRuntimeOnly(libs.junit.jupiter.engine)
}

test {
Expand Down
1 change: 0 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ rxjava2 = { module = "io.reactivex.rxjava2:rxjava" }
rxjava3 = { module = "io.reactivex.rxjava3:rxjava" }
testcontainers-spock = { module = "org.testcontainers:spock" }

kotlintest-runner-junit5 = { module = "io.kotlintest:kotlintest-runner-junit5", version.ref = "kotlintest-runner-junit5" }
kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_PROPERTY_NAMING_STRATEGY,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_VIEWS_SPEC,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_JSON_FORMAT,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_ENVIRONMENTS,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_TARGET_FILE,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_ADDITIONAL_FILES,
OpenApiApplicationVisitor.MICRONAUT_OPENAPI_CONFIG_FILE,
Expand Down Expand Up @@ -108,22 +109,18 @@ public class OpenApiApplicationVisitor extends AbstractOpenApiVisitor implements
* System property that specifies the location of additional swagger YAML and JSON files to read from.
*/
public static final String MICRONAUT_OPENAPI_ADDITIONAL_FILES = "micronaut.openapi.additional.files";

/**
* Default openapi config file.
*/
public static final String OPENAPI_CONFIG_FILE = "openapi.properties";

/**
* The name of the entry for Endpoint class tags in the context.
*/
public static final String MICRONAUT_OPENAPI_ENDPOINT_CLASS_TAGS = "micronaut.openapi.endpoint.class.tags";

/**
* The name of the entry for Endpoint servers in the context.
*/
public static final String MICRONAUT_OPENAPI_ENDPOINT_SERVERS = "micronaut.openapi.endpoint.servers";

/**
* The name of the entry for Endpoint security requirements in the context.
*/
Expand All @@ -132,6 +129,10 @@ public class OpenApiApplicationVisitor extends AbstractOpenApiVisitor implements
* Is this property true, output file format will be JSON, otherwise YAML.
*/
public static final String MICRONAUT_OPENAPI_JSON_FORMAT = "micronaut.openapi.json.format";
/**
* Active micronaut environments which will be used for @Requires annotations.
*/
public static final String MICRONAUT_OPENAPI_ENVIRONMENTS = "micronaut.openapi.environments";

private static final String MICRONAUT_OPENAPI_PROPERTIES = "micronaut.openapi.properties";
private static final String MICRONAUT_OPENAPI_ENDPOINTS = "micronaut.openapi.endpoints";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
*/
package io.micronaut.openapi.visitor;

import io.micronaut.context.RequiresCondition;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.Experimental;
import io.micronaut.core.type.Argument;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.core.util.StringUtils;
import io.micronaut.http.HttpMethod;
import io.micronaut.http.MediaType;
Expand All @@ -27,6 +31,7 @@
import io.micronaut.http.annotation.UriMapping;
import io.micronaut.http.uri.UriMatchTemplate;
import io.micronaut.inject.ast.ClassElement;
import io.micronaut.inject.ast.Element;
import io.micronaut.inject.ast.MethodElement;
import io.micronaut.inject.visitor.TypeElementVisitor;
import io.micronaut.inject.visitor.VisitorContext;
Expand All @@ -44,6 +49,10 @@
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.MICRONAUT_OPENAPI_ENVIRONMENTS;
import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.readOpenApiConfigFile;

/**
* A {@link TypeElementVisitor} the builds the Swagger model from Micronaut controllers at compile time.
Expand Down Expand Up @@ -72,9 +81,60 @@ public OpenApiControllerVisitor(List<AnnotationValue<Tag>> additionalTags,
this.customUri = customUri;
}

private List<String> getActiveEnvironments(VisitorContext context) {
Optional<List<String>> activeEnvsOpt = context.get(MICRONAUT_OPENAPI_ENVIRONMENTS, Argument.LIST_OF_STRING);
if (activeEnvsOpt.isPresent()) {
return activeEnvsOpt.get();
}
String activeEnv = getConfigurationProperty(MICRONAUT_OPENAPI_ENVIRONMENTS, context);
List<String> activeEnvs;
if (StringUtils.isNotEmpty(activeEnv)) {
activeEnvs = Stream.of(activeEnv)
.filter(StringUtils::isNotEmpty)
.flatMap(s -> Arrays.stream(s.split(",")))
.map(String::trim)
.collect(Collectors.toList());
} else {
activeEnvs = new ArrayList<>();
}
context.put(MICRONAUT_OPENAPI_ENVIRONMENTS, activeEnvs);
return activeEnvs;
}

private boolean ignoreByRequires(Element element, VisitorContext context) {
List<AnnotationValue<Requires>> requiresAnnotations = element.getDeclaredAnnotationValuesByType(Requires.class);
if (CollectionUtils.isEmpty(requiresAnnotations)) {
return false;
}
List<String> activeEnvs = getActiveEnvironments(context);
if (activeEnvs.isEmpty()) {
return false;
}

// check env and notEnv
for (AnnotationValue<Requires> requiresAnn : requiresAnnotations) {
Optional<String[]> reqEnvs = requiresAnn.get(RequiresCondition.MEMBER_ENV, String[].class);
if (reqEnvs.isPresent()) {
boolean result = Arrays.stream(reqEnvs.get()).anyMatch(activeEnvs::contains);
if (!result) {
return true;
}
}
Optional<String[]> reqNotEnvs = requiresAnn.get(RequiresCondition.MEMBER_NOT_ENV, String[].class);
if (reqNotEnvs.isPresent()) {
boolean result = Arrays.stream(reqNotEnvs.get()).noneMatch(activeEnvs::contains);
if (!result) {
return true;
}
}
}
return false;
}

@Override
protected boolean ignore(ClassElement element, VisitorContext context) {
return !element.isAnnotationPresent(Controller.class);
return !element.isAnnotationPresent(Controller.class)
|| ignoreByRequires(element, context);
}

@Override
Expand All @@ -87,7 +147,12 @@ protected boolean ignore(MethodElement element, VisitorContext context) {
|| ignore(element.getDeclaringType(), context)
|| element.isPrivate()
|| element.isStatic()
|| element.isAnnotationPresent(Hidden.class);
|| element.isAnnotationPresent(Hidden.class)
|| ignoreByRequires(element, context);
}

private String getConfigurationProperty(String key, VisitorContext context) {
return System.getProperty(key, readOpenApiConfigFile(context).getProperty(key));
}

@Override
Expand Down
Loading