-
Notifications
You must be signed in to change notification settings - Fork 113
#1357 Load openapi specifications from jar maven dependency (GAV) of project #1376
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
Open
michaelsonnleitner
wants to merge
12
commits into
quarkiverse:main
Choose a base branch
from
michaelsonnleitner:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+646
−155
Open
Changes from 8 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
8e7ccf8
Load openapi specifications from jar maven dependency (GAV) of projec…
05456ff
added include-gavs option & docu
764e077
formating
bacd9a4
Merge branch 'quarkiverse:main' into main
michaelsonnleitner 4cbead0
Merge remote-tracking branch 'origin/main'
bfd4e5b
review
3b0bca1
review
5723442
doc added
e80effd
review
6cd1a3a
Merge branch 'quarkiverse:main' into main
michaelsonnleitner 040da2f
review#2
5983064
Merge remote-tracking branch 'origin/main'
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| * text eol=lf | ||
| *.jar -text -eol -working-tree-encoding -merge -diff |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
...t/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/GavItemConfig.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package io.quarkiverse.openapi.generator.deployment; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Optional; | ||
|
|
||
| import io.smallrye.config.WithDefault; | ||
| import io.smallrye.config.WithName; | ||
|
|
||
| /* | ||
| * Model for the configuration of this extension. | ||
| * It's used for documentation purposes only. | ||
| * The configuration is consumed in the codegen phase, before build time. | ||
| * Not meant to be used outside this scope. | ||
| * Config items can be applied only on gav | ||
| */ | ||
| public interface GavItemConfig extends CommonItemConfig { | ||
| /** | ||
| * List of OpenAPI spec files in GAV to be generated | ||
| */ | ||
| @WithName("spec-files") | ||
| @WithDefault("openapi.yaml") | ||
| Optional<List<String>> gavSpecFiles(); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
...e/openapi/generator/deployment/codegen/AbstractGAVCoordinateOpenApiSpecInputProvider.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| package io.quarkiverse.openapi.generator.deployment.codegen; | ||
|
|
||
| import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.*; | ||
| import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.ConfigName.*; | ||
|
|
||
| import java.nio.file.Path; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import java.util.function.Predicate; | ||
|
|
||
| import org.jboss.logging.Logger; | ||
|
|
||
| import io.quarkus.bootstrap.prebuild.CodeGenException; | ||
| import io.quarkus.deployment.CodeGenContext; | ||
| import io.quarkus.maven.dependency.ResolvedDependency; | ||
| import io.smallrye.config.common.utils.StringUtil; | ||
|
|
||
| abstract class AbstractGAVCoordinateOpenApiSpecInputProvider implements OpenApiSpecInputProvider { | ||
| private static final Logger LOG = Logger.getLogger(AbstractGAVCoordinateOpenApiSpecInputProvider.class); | ||
|
|
||
| @Override | ||
| public List<SpecInputModel> read(CodeGenContext context) throws CodeGenException { | ||
| if (!context.config().getOptionalValue(getGlobalConfigName(GAV_SCANNING), Boolean.class) | ||
| .orElse(true)) { | ||
| LOG.debug("GAV scanning is disabled."); | ||
| return List.of(); | ||
| } | ||
|
|
||
| List<String> gavsToExclude = context.config().getOptionalValues(getGlobalConfigName(EXCLUDE_GAVS), String.class) | ||
| .orElse(List.of()); | ||
| String artifactIdFilter = context.config().getOptionalValue(getGlobalConfigName(ARTIFACT_ID_FILTER), String.class) | ||
| .filter(Predicate.not(String::isBlank)) | ||
| .orElse(".*openapi.*"); | ||
|
|
||
| List<ResolvedDependency> dependencies = context.applicationModel().getDependencies().stream() | ||
| .filter(rd -> getSupportedExtensions().contains(rd.getType().toLowerCase())) | ||
| .filter(rd -> rd.getArtifactId().matches(artifactIdFilter)) | ||
| .filter(rd -> !gavsToExclude.contains(rd.getKey().toGacString())) | ||
| .filter(rd -> specificGAVSpecInputProviderFilter(context, rd.getKey().toGacString())) | ||
| .toList(); | ||
|
|
||
| if (dependencies.isEmpty()) { | ||
| LOG.debug("No suitable GAV dependencies found. ArtifactIdFilter was %s and gavsToExclude were %s." | ||
| .formatted(artifactIdFilter, gavsToExclude)); | ||
| return List.of(); | ||
| } | ||
|
|
||
| var inputModels = new ArrayList<SpecInputModel>(); | ||
| for (ResolvedDependency dependency : dependencies) { | ||
| var gacString = StringUtil.replaceNonAlphanumericByUnderscores(dependency.getKey().toGacString()); | ||
| var path = dependency.getResolvedPaths().stream().findFirst() | ||
| .orElseThrow(() -> new CodeGenException("Could not find maven path of %s.".formatted(gacString))); | ||
| addInputModels(context, gacString, path, inputModels); | ||
| } | ||
| return inputModels; | ||
| } | ||
|
|
||
| protected abstract Set<String> getSupportedExtensions(); | ||
|
|
||
| /** | ||
| * Adds input models to the provided list based on the given context, GAC string, and path. | ||
| * This method is implemented by subclasses to generate or retrieve the appropriate | ||
| * {@code SpecInputModel} instances that will be processed during code generation. | ||
| * | ||
| * @param context the code generation context, providing access to configuration and utilities | ||
| * @param gacString the GAC (Group, Artifact, Classifier) string representing the dependency identifier | ||
| * @param path the path to the file or directory containing the input specification(s) | ||
| * @param inputModels the list to which the generated {@code SpecInputModel} instances are added | ||
| * @throws CodeGenException if an error occurs while processing the input specifications | ||
| */ | ||
| protected abstract void addInputModels(CodeGenContext context, | ||
| String gacString, | ||
| Path path, | ||
| List<SpecInputModel> inputModels) throws CodeGenException; | ||
|
|
||
| /** | ||
| * Filters dependencies based on specific criteria defined in the implementing class. | ||
| * This method is invoked as part of the dependency resolution process to determine | ||
| * whether a dependency identified by its GAC string should be included for further processing. | ||
| * | ||
| * @param context the code generation context, providing access to configuration and other utilities | ||
| * @param gacString the GAC (Group, Artifact, Classifier) string representing the dependency identifier | ||
| * @return true if the dependency matches the filter criteria and should be included; false otherwise | ||
| */ | ||
| protected abstract boolean specificGAVSpecInputProviderFilter(CodeGenContext context, String gacString); | ||
| } |
111 changes: 111 additions & 0 deletions
111
...e/openapi/generator/deployment/codegen/JarOrZipGAVCoordinateOpenApiSpecInputProvider.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| package io.quarkiverse.openapi.generator.deployment.codegen; | ||
|
|
||
| import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.*; | ||
| import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.ConfigName.*; | ||
|
|
||
| import java.io.IOException; | ||
| import java.nio.file.Files; | ||
| import java.nio.file.Path; | ||
| import java.nio.file.Paths; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| import io.quarkus.bootstrap.prebuild.CodeGenException; | ||
| import io.quarkus.deployment.CodeGenContext; | ||
|
|
||
| /** | ||
| * Provides OpenAPI specification input from Maven GAV (GroupId:ArtifactId:Version) dependencies | ||
| * packaged as JAR or ZIP files. | ||
| * <p> | ||
| * This provider extends the {@link AbstractGAVCoordinateOpenApiSpecInputProvider} and is responsible for | ||
| * scanning application dependencies to identify JAR or ZIP files that contain OpenAPI specifications | ||
| * (e.g., `openapi.yaml`). | ||
| * </p> | ||
| * | ||
| * <h2>Supported File Types</h2> | ||
| * <p> | ||
| * The provider specifically supports dependencies packaged as: | ||
| * </p> | ||
| * <ul> | ||
| * <li>JAR files</li> | ||
| * <li>ZIP files</li> | ||
| * </ul> | ||
| * | ||
| * <h2>Scanning Behavior</h2> | ||
| * <p> | ||
| * The provider performs the following steps: | ||
| * </p> | ||
| * <ol> | ||
| * <li>Checks if GAV scanning is enabled via configuration (enabled by default)</li> | ||
| * <li>Filters dependencies by artifact type (jar/zip)</li> | ||
| * <li>Applies artifact ID filtering using a regex pattern</li> | ||
| * <li>Excludes specific GAVs based on configuration</li> | ||
| * <li>Includes specific GAVs based on configuration if not available no GAVs are used</li> | ||
| * <li>Creates {@link ZippedSpecInputModel} instances for each matching dependency and openAPI specification file</li> | ||
| * </ol> | ||
| * | ||
| * <h2>Configuration</h2> | ||
| * <p> | ||
| * The provider respects the following configuration properties: | ||
| * </p> | ||
| * <ul> | ||
| * <li>{@code quarkus.openapi-generator.codegen.gav-scanning} - Enable/disable GAV scanning</li> | ||
| * <li>{@code quarkus.openapi-generator.codegen.artifact-id-filter} - Regex pattern for artifact ID filtering</li> | ||
| * <li>{@code quarkus.openapi-generator.codegen.exclude-gavs} - List of GAV coordinates to exclude | ||
| * (format: groupId:artifactId:classifier)</li> | ||
| * <li>{@code quarkus.openapi-generator.codegen.gav.com_sample_customer_service_openapi.spec-files} - List of | ||
| * openAPI specification files in com.sample:customer-service-openapi:jar</li> | ||
| * </ul> | ||
| * | ||
| * <h2>Example Usage</h2> | ||
| * | ||
| * <pre> | ||
| * # application.properties | ||
| * quarkus.openapi-generator.codegen.gav-scanning=true | ||
| * quarkus.openapi-generator.codegen.artifact-id-filter=.*api.* | ||
| * quarkus.openapi-generator.codegen.exclude-gavs=com.example:old-api | ||
| * quarkus.openapi-generator.codegen.gav.com_sample_customer_service_api.spec-files=customer.yaml,another.yaml | ||
| * </pre> | ||
| * | ||
| * @see AbstractGAVCoordinateOpenApiSpecInputProvider | ||
| * @see ZippedSpecInputModel | ||
| * @see CodeGenContext | ||
| */ | ||
| public class JarOrZipGAVCoordinateOpenApiSpecInputProvider extends AbstractGAVCoordinateOpenApiSpecInputProvider { | ||
| private static final Set<String> SUPPORTED_EXTENSIONS = Set.of("jar", "zip"); | ||
|
|
||
| @Override | ||
| protected void addInputModels(CodeGenContext context, | ||
| String gacString, | ||
| Path path, | ||
| List<SpecInputModel> inputModels) throws CodeGenException { | ||
| List<String> rootFilesOfSpecOfDependency = context.config() | ||
| .getOptionalValues(getGavConfigName(SPEC_FILES, Paths.get(gacString)), String.class) | ||
| .orElse(List.of("openapi.yaml")); | ||
| for (String rootFileOfSpecForDependency : rootFilesOfSpecOfDependency) { | ||
| try { | ||
| inputModels.add(new ZippedSpecInputModel( | ||
| gacString, | ||
| rootFileOfSpecForDependency, | ||
| Files.newInputStream(path))); | ||
| } catch (IOException e) { | ||
| throw new CodeGenException( | ||
| "Could not open input stream of %s from %s.".formatted(gacString, path.toString()), | ||
| e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| protected Set<String> getSupportedExtensions() { | ||
| return SUPPORTED_EXTENSIONS; | ||
| } | ||
|
|
||
| @Override | ||
| protected boolean specificGAVSpecInputProviderFilter(final CodeGenContext context, final String gacString) { | ||
| return new HashSet<>(context.config().getOptionalValues(getGlobalConfigName(INCLUDE_GAVS), String.class) | ||
| .orElse(List.of())) // default to empty list to disable all if not specified | ||
| .contains(gacString); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.