├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── ci.yaml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── mvnvm.properties ├── pom.xml └── src ├── it ├── ISSUE-25 │ ├── invoker.properties │ ├── pom.xml │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── foo │ │ │ │ ├── Application.java │ │ │ │ └── Service.java │ │ │ └── resources │ │ │ ├── swagger-expected.json │ │ │ └── swagger-expected.yaml │ └── verify.bsh └── settings.xml ├── main └── java │ └── io │ └── openapitools │ └── swagger │ ├── ClassUtils.java │ ├── GenerateMojo.java │ ├── JaxRSScanner.java │ ├── OpenAPISorter.java │ ├── OutputFormat.java │ └── config │ ├── SwaggerComponents.java │ ├── SwaggerConfig.java │ ├── SwaggerContact.java │ ├── SwaggerExternalDoc.java │ ├── SwaggerFlows.java │ ├── SwaggerInfo.java │ ├── SwaggerLicense.java │ ├── SwaggerSecurityRequirement.java │ ├── SwaggerSecurityScheme.java │ ├── SwaggerServer.java │ ├── SwaggerServerVariable.java │ └── SwaggerTag.java └── test ├── java └── io │ └── openapitools │ └── swagger │ ├── GenerateMojoIT.java │ ├── MavenProjectStub.java │ ├── OpenApiSorterTest.java │ └── example │ ├── AccountServiceExposure.java │ ├── alternate │ ├── APIDefinition.java │ ├── AlternateResource.java │ └── ManipulatorListener.java │ ├── app │ └── RestApplication.java │ └── model │ ├── AccountRepresentation.java │ ├── AccountUpdateRepresentation.java │ ├── AccountsRepresentation.java │ ├── TransactionRepresentation.java │ └── TransactionsRepresentation.java └── resources ├── descriptions.md ├── expectedOutput ├── api │ ├── swagger.json │ └── swagger.yaml ├── application │ └── swagger.json ├── application_scan │ └── swagger.json ├── default │ └── swagger.json ├── full │ ├── open-api.json │ └── open-api.yaml ├── fullpretty │ ├── open-api.json │ └── open-api.yaml ├── recursive │ └── swagger.json └── semifull │ ├── swagger.json │ └── swagger.yaml ├── generate-mojo-application-scan.xml ├── generate-mojo-application.xml ├── generate-mojo-defaults-pom.xml ├── generate-mojo-full-nofilename-pom.xml ├── generate-mojo-full-pom.xml ├── generate-mojo-full-pretty-pom.xml ├── generate-mojo-pom.xml └── generate-mojo-recursive-pom.xml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Additional context** 17 | Add any other context about the problem here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: [push,pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | java: [ 8, 12, 15 ] 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Set Java 14 | uses: actions/setup-java@v1 15 | with: 16 | java-version: ${{ matrix.java }} 17 | - name: Cache Maven packages 18 | uses: actions/cache@v2 19 | with: 20 | path: ~/.m2 21 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 22 | restore-keys: ${{ runner.os }}-m2 23 | - name: Build with Maven 24 | run: mvn --batch-mode --update-snapshots verify -Dgpg.skip=true 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .idea 3 | *.iml 4 | .settings -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | install: mvn install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true -B -V 4 | script: mvn clean verify -Dgpg.skip=true -B 5 | 6 | jdk: 7 | - openjdk8 8 | - openjdk11 9 | - openjdk13 10 | 11 | cache: 12 | directories: 13 | - $HOME/.m2 14 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at thor.lange@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Open API Tools 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swagger Maven Plugin 2 | 3 | This plugin is intended to use the [Swagger Core library](https://github.com/swagger-api/swagger-core) to generate 4 | OpenAPI documentation from a JAX-RS based REST service with as little change as possible. This allows for @SwaggerDefinition, @ReaderListener and ModelConverters to work the same way as with the core Swagger library. 5 | 6 | 7 | # Status 8 | 9 | The plugin is considered production ready. The version 2.x.x of the plugin is supporting generation of OpenAPI version 3 specifications using Swagger 2.x. To generate OpenAPI version 2 specifications using Swagger 1.x use the latest 1.x.x version of the plugin. 10 | 11 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.openapitools.swagger/swagger-maven-plugin/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.openapitools.swagger/swagger-maven-plugin/) 12 | [![Javadoc](https://javadoc.io/badge/io.openapitools.swagger/swagger-maven-plugin/badge.svg)](https://www.javadoc.io/doc/io.openapitools.swagger/swagger-maven-plugin) 13 | [![Build status](https://travis-ci.org/openapi-tools/swagger-maven-plugin.svg?branch=master)](https://travis-ci.org/openapi-tools/swagger-maven-plugin) 14 | [![Known Vulnerabilities](https://snyk.io/test/github/openapi-tools/swagger-maven-plugin/badge.svg)](https://snyk.io/test/github/openapi-tools/swagger-maven-plugin) 15 | 16 | 17 | # Usage 18 | 19 | To have Swagger generate the OpenAPI specifications as part of the build add in the plugin to the POM. 20 | 21 | ```xml 22 | 23 | 24 | ... 25 | 26 | io.openapitools.swagger 27 | swagger-maven-plugin 28 | 29 | 30 | io.openapitools.swagger.example 31 | io.openapitools.swagger.example.alternate 32 | 33 | ${basedir}/target/ 34 | swagger 35 | JSON,YAML 36 | true 37 | 38 | 39 | 40 | 41 | generate 42 | 43 | 44 | 45 | 46 | ... 47 | 48 | 49 | ``` 50 | 51 | This will run the generation in the prepare-package lifecycle stage of the Maven build. 52 | 53 | ## Specifying Packages with JAX-RS Endpoints 54 | 55 | The packages containing JAX-RS endpoints must be configured using the resourcePackages element. See the minimal configuration above. 56 | 57 | ## Properties of Swagger model 58 | 59 | Most general properties of the Swagger model is configurable using the swaggerConfig element. Note this may also be configured through the @OpenAPIDefinition annotation - see [Customizing your auto-generated Swagger Definitions](http://swagger.io/customizing-your-auto-generated-swagger-definitions-in-1-5-x/). 60 | 61 | ```xml 62 | 63 | io.openapitools.swagger 64 | swagger-maven-plugin 65 | 66 | 67 | 68 | 69 | https://services.exmple.it/base/path 70 | Endpoint URL 71 | 72 | 73 | 74 | Title 75 | 1.0.0 76 | Terms 77 | 78 | e@mail.com 79 | My Name 80 | https://google.com 81 | 82 | 83 | https://license 84 | MIT 85 | 86 | 87 | my-custom-field-1 88 | my-custom-field-2 89 | 90 | 91 | src/test/resources/descriptions.md 92 | 93 | ``` 94 | 95 | 96 | ## Deploying 97 | 98 | The generated OpenAPI specifications may be installed and deployed as Maven artifact. To enable this add the configuration parameter attachSwaggerArtifact. 99 | 100 | ```xml 101 | 102 | io.openapitools.swagger 103 | swagger-maven-plugin 104 | 105 | true 106 | ``` 107 | 108 | # Acknowledgement 109 | 110 | Thanks to [Yukai Kong](https://github.com/kongchen) for his work on 111 | [Swagger Maven plugin](https://github.com/kongchen/swagger-maven-plugin). This plugin is heavily inspired by that. 112 | -------------------------------------------------------------------------------- /mvnvm.properties: -------------------------------------------------------------------------------- 1 | mvn_version=3.6.3 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | Swagger Maven Plugin 7 | io.openapitools.swagger 8 | 2.1.7-SNAPSHOT 9 | swagger-maven-plugin 10 | maven-plugin 11 | 12 | Maven plugin to generate OpenAPI documentation using Swagger. 13 | https://github.com/openapi-tools/swagger-maven-plugin 14 | 15 | 16 | 17 | MIT License 18 | http://www.opensource.org/licenses/mit-license.php 19 | 20 | 21 | 22 | 23 | 24 | Thor Anker Kvisgård Lange 25 | thor.lange@gmail.com 26 | Open API Tools 27 | https://github.com/openapitools 28 | 29 | 30 | 31 | 32 | scm:git:https://github.com/openapi-tools/swagger-maven-plugin.git 33 | scm:git:https://github.com/openapi-tools/swagger-maven-plugin.git 34 | https://github.com/openapi-tools/swagger-maven-plugin/tree/master 35 | HEAD 36 | 37 | 38 | 39 | 40 | ossrh 41 | https://oss.sonatype.org/content/repositories/snapshots 42 | 43 | 44 | ossrh 45 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 46 | 47 | 48 | 49 | 50 | UTF-8 51 | UTF-8 52 | 53 | 2.12.2 54 | 30.0-jre 55 | 1.8.0 56 | 2.7.0-01 57 | 2.0.4-04 58 | 1.0.8 59 | 2.1.7 60 | 2.3.0 61 | 2.1 62 | 4.13.1 63 | 3.5 64 | 3.6.0 65 | 3.3.0 66 | 3.2.0 67 | 0.9.12 68 | 1.7.29 69 | 70 | 71 | 72 | 73 | io.swagger.core.v3 74 | swagger-jaxrs2 75 | ${io.swagger.core.v3.version} 76 | 77 | 78 | javax.ws.rs 79 | javax.ws.rs-api 80 | ${javax.ws.rs.version} 81 | 82 | 83 | org.slf4j 84 | slf4j-api 85 | ${org.slf4j.version} 86 | 87 | 88 | org.apache.maven.plugin-tools 89 | maven-plugin-annotations 90 | ${org.apache.maven.maven-plugin-annotations.version} 91 | 92 | 93 | org.apache.maven 94 | maven-plugin-api 95 | ${org.apache.maven.version} 96 | 97 | 98 | org.apache.maven 99 | maven-core 100 | ${org.apache.maven.version} 101 | 102 | 103 | org.apache.maven 104 | maven-artifact 105 | ${org.apache.maven.version} 106 | 107 | 108 | org.reflections 109 | reflections 110 | ${org.reflections.version} 111 | 112 | 113 | javax.xml.bind 114 | jaxb-api 115 | ${javax.xml.bin.jaxb-api.version} 116 | true 117 | 118 | 119 | 120 | 121 | com.fasterxml.jackson.core 122 | jackson-databind 123 | ${com.fasterxml.jackson.core.version} 124 | 125 | 126 | 127 | com.google.guava 128 | guava 129 | ${com.google.guava.version} 130 | 131 | 132 | 133 | junit 134 | junit 135 | ${junit.version} 136 | test 137 | 138 | 139 | org.slf4j 140 | slf4j-simple 141 | ${org.slf4j.version} 142 | test 143 | 144 | 145 | org.mockito 146 | mockito-core 147 | ${org.mockito.version} 148 | test 149 | 150 | 151 | org.apache.maven.plugin-testing 152 | maven-plugin-testing-harness 153 | ${org.apache.maven.plugin-testing.version} 154 | test 155 | 156 | 157 | org.apache.maven 158 | maven-compat 159 | ${org.apache.maven.version} 160 | test 161 | 162 | 163 | io.openapitools.jackson.dataformat 164 | jackson-dataformat-hal 165 | ${io.openapitools.jackson.dataformat.version} 166 | test 167 | 168 | 169 | org.codehaus.groovy 170 | groovy-eclipse-compiler 171 | ${groovy.eclipse.compiler.version} 172 | test 173 | 174 | 175 | org.codehaus.groovy 176 | groovy-eclipse-batch 177 | ${groovy-eclipse-batch.version} 178 | test 179 | 180 | 181 | org.codehaus.groovy 182 | groovy-all 183 | ${groovy.version} 184 | test 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | org.apache.maven.plugins 193 | maven-plugin-plugin 194 | 3.5 195 | 196 | 197 | org.apache.maven.plugins 198 | maven-compiler-plugin 199 | 3.8.0 200 | 201 | 1.8 202 | 1.8 203 | 204 | -Xlint 205 | 206 | 207 | 208 | 209 | org.apache.maven.plugins 210 | maven-surefire-plugin 211 | 2.22.0 212 | 213 | 214 | org.apache.maven.plugins 215 | maven-failsafe-plugin 216 | 2.22.0 217 | 218 | 219 | 220 | integration-test 221 | verify 222 | 223 | 224 | 225 | 226 | 227 | org.apache.maven.plugins 228 | maven-invoker-plugin 229 | 3.2.0 230 | 231 | 232 | integration-test 233 | 234 | 235 | install 236 | run 237 | 238 | 239 | 240 | 241 | src/it 242 | ${project.build.directory}/it 243 | 244 | */pom.xml 245 | 246 | verify 247 | ${project.build.directory}/local-repo 248 | src/it/settings.xml 249 | true 250 | false 251 | 252 | ${https.protocols} 253 | 254 | 255 | clean 256 | package 257 | 258 | 259 | 260 | 261 | org.apache.maven.plugins 262 | maven-gpg-plugin 263 | 1.6 264 | 265 | 266 | sign-artifacts 267 | verify 268 | 269 | sign 270 | 271 | 272 | 273 | 274 | 275 | org.apache.maven.plugins 276 | maven-source-plugin 277 | 3.0.1 278 | 279 | 280 | attach-sources 281 | 282 | jar-no-fork 283 | 284 | 285 | 286 | 287 | 288 | org.apache.maven.plugins 289 | maven-javadoc-plugin 290 | 3.1.1 291 | 292 | 1.8 293 | 294 | 295 | 296 | attach-javadocs 297 | 298 | jar 299 | 300 | 301 | 302 | 303 | 304 | org.apache.maven.plugins 305 | maven-release-plugin 306 | 2.5.3 307 | 308 | v@{project.version} 309 | 310 | 311 | 312 | 313 | 314 | 315 | -------------------------------------------------------------------------------- /src/it/ISSUE-25/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals = clean package -------------------------------------------------------------------------------- /src/it/ISSUE-25/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | io.openapitools.swagger.it 7 | issue-25 8 | 1.0-SNAPSHOT 9 | 10 | IT that asserts that compile and runtime deps of project are correctly handled. 11 | 12 | 13 | 14 | javax 15 | javaee-api 16 | 8.0 17 | provided 18 | 19 | 20 | commons-fileupload 21 | commons-fileupload 22 | 1.4 23 | 24 | 25 | 26 | 27 | UTF-8 28 | 29 | 30 | 31 | 32 | 33 | io.openapitools.swagger 34 | swagger-maven-plugin 35 | @project.version@ 36 | 37 | 38 | foo 39 | 40 | ${project.build.directory} 41 | swagger 42 | JSON,YAML 43 | true 44 | 45 | 46 | 47 | prepare-package 48 | 49 | generate 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-compiler-plugin 58 | 3.8.0 59 | 60 | 1.8 61 | 1.8 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/it/ISSUE-25/src/main/java/foo/Application.java: -------------------------------------------------------------------------------- 1 | package foo; 2 | 3 | import javax.ws.rs.ApplicationPath; 4 | 5 | @ApplicationPath("/") 6 | public class Application extends javax.ws.rs.core.Application { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/it/ISSUE-25/src/main/java/foo/Service.java: -------------------------------------------------------------------------------- 1 | package foo; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.ws.rs.Consumes; 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.Produces; 11 | import javax.ws.rs.core.Context; 12 | import javax.ws.rs.core.MediaType; 13 | 14 | import org.apache.commons.fileupload.FileUploadException; 15 | 16 | @Path("/hello") 17 | public class Service { 18 | 19 | @GET 20 | @Path("/get") 21 | @Produces(MediaType.APPLICATION_JSON) 22 | @Consumes(MediaType.MULTIPART_FORM_DATA) 23 | public List get(@Context HttpServletRequest request) throws FileUploadException { 24 | return Arrays.asList(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/it/ISSUE-25/src/main/resources/swagger-expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi" : "3.0.1", 3 | "paths" : { 4 | "/hello/get" : { 5 | "get" : { 6 | "operationId" : "get", 7 | "responses" : { 8 | "default" : { 9 | "description" : "default response", 10 | "content" : { 11 | "application/json" : { 12 | "schema" : { 13 | "type" : "array", 14 | "items" : { 15 | "type" : "string" 16 | } 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/it/ISSUE-25/src/main/resources/swagger-expected.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | paths: 3 | /hello/get: 4 | get: 5 | operationId: get 6 | responses: 7 | default: 8 | description: default response 9 | content: 10 | application/json: 11 | schema: 12 | type: array 13 | items: 14 | type: string 15 | -------------------------------------------------------------------------------- /src/it/ISSUE-25/verify.bsh: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.nio.*; 3 | import java.nio.file.*; 4 | import java.nio.charset.*; 5 | 6 | File expectedFile = new File(basedir, "target/classes/swagger-expected.json"); 7 | String expected = new String(Files.readAllBytes(expectedFile.toPath()), StandardCharsets.UTF_8) 8 | .replaceAll("\\r\\n?", "\n"); 9 | 10 | File actualFile = new File(basedir, "target/swagger.json"); 11 | String actual = new String(Files.readAllBytes(actualFile.toPath()), StandardCharsets.UTF_8) 12 | .replaceAll("\\r\\n?", "\n"); 13 | 14 | if (!expected.equals(actual)) { 15 | throw new AssertionError("Swagger file does not match the expected one"); 16 | } -------------------------------------------------------------------------------- /src/it/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | it-repo 6 | 7 | true 8 | 9 | 10 | 11 | local.central 12 | @localRepositoryUrl@ 13 | 14 | true 15 | 16 | 17 | true 18 | 19 | 20 | 21 | 22 | 23 | local.central 24 | @localRepositoryUrl@ 25 | 26 | true 27 | 28 | 29 | true 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/ClassUtils.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | final class ClassUtils { 4 | 5 | private ClassUtils() { 6 | } 7 | 8 | public static Class loadClass(String className, ClassLoader classLoader) { 9 | try { 10 | return Class.forName(className, true, classLoader); 11 | } catch (ClassNotFoundException e) { 12 | return null; 13 | } 14 | } 15 | 16 | public static T createInstance(Class clazz) { 17 | try { 18 | return clazz.getDeclaredConstructor().newInstance(); 19 | } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { 20 | return null; 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/GenerateMojo.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | import javax.ws.rs.core.Application; 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.net.MalformedURLException; 7 | import java.net.URL; 8 | import java.net.URLClassLoader; 9 | import java.nio.file.Paths; 10 | import java.util.Collection; 11 | import java.util.Collections; 12 | import java.util.LinkedHashSet; 13 | import java.util.Set; 14 | 15 | import io.openapitools.swagger.config.SwaggerConfig; 16 | import io.swagger.v3.jaxrs2.Reader; 17 | import io.swagger.v3.oas.models.OpenAPI; 18 | import org.apache.maven.artifact.DependencyResolutionRequiredException; 19 | import org.apache.maven.plugin.AbstractMojo; 20 | import org.apache.maven.plugin.MojoExecutionException; 21 | import org.apache.maven.plugin.MojoFailureException; 22 | import org.apache.maven.plugins.annotations.Component; 23 | import org.apache.maven.plugins.annotations.LifecyclePhase; 24 | import org.apache.maven.plugins.annotations.Mojo; 25 | import org.apache.maven.plugins.annotations.Parameter; 26 | import org.apache.maven.plugins.annotations.ResolutionScope; 27 | import org.apache.maven.project.MavenProject; 28 | import org.apache.maven.project.MavenProjectHelper; 29 | 30 | /** 31 | * Maven mojo to generate OpenAPI documentation document based on Swagger. 32 | */ 33 | @Mojo(name = "generate", defaultPhase = LifecyclePhase.PREPARE_PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) 34 | public class GenerateMojo extends AbstractMojo { 35 | 36 | /** 37 | * Skip the execution. 38 | */ 39 | @Parameter(name = "skip", property = "openapi.generation.skip", required = false, defaultValue = "false") 40 | private Boolean skip; 41 | 42 | /** 43 | * Static information to provide for the generation. 44 | */ 45 | @Parameter 46 | private SwaggerConfig swaggerConfig; 47 | 48 | /** 49 | * List of packages which contains API resources. This is not recursive. 50 | */ 51 | @Parameter 52 | private Set resourcePackages; 53 | 54 | /** 55 | * Recurse into resourcePackages child packages. 56 | */ 57 | @Parameter(required = false, defaultValue = "false") 58 | private Boolean useResourcePackagesChildren; 59 | 60 | /** 61 | * Directory to contain generated documentation. 62 | */ 63 | @Parameter(defaultValue = "${project.build.directory}") 64 | private File outputDirectory; 65 | 66 | /** 67 | * Filename to use for the generated documentation. 68 | */ 69 | @Parameter 70 | private String outputFilename = "swagger"; 71 | 72 | /** 73 | * Choosing the output format. Supports JSON or YAML. 74 | */ 75 | @Parameter 76 | private Set outputFormats = Collections.singleton(OutputFormat.JSON); 77 | 78 | /** 79 | * Attach generated documentation as artifact to the Maven project. If true documentation will be deployed along 80 | * with other artifacts. 81 | */ 82 | @Parameter(defaultValue = "false") 83 | private boolean attachSwaggerArtifact; 84 | 85 | /** 86 | * Specifies the implementation of {@link Application}. If the class is not specified, 87 | * the resource packages are scanned for the {@link Application} implementations 88 | * automatically. 89 | */ 90 | @Parameter(name = "applicationClass", defaultValue = "") 91 | private String applicationClass; 92 | 93 | @Parameter(defaultValue = "${project}", readonly = true) 94 | private MavenProject project; 95 | 96 | /** 97 | * When true, the plugin produces a pretty-printed JSON Swagger specification. Note that this parameter doesn't 98 | * have any effect on the generation of the YAML version because YAML is pretty-printed by nature. 99 | */ 100 | @Parameter(defaultValue = "false") 101 | private boolean prettyPrint; 102 | 103 | @Component 104 | private MavenProjectHelper projectHelper; 105 | 106 | @Override 107 | public void execute() throws MojoExecutionException, MojoFailureException { 108 | if (skip != null && skip) { 109 | getLog().info("OpenApi generation is skipped."); 110 | return; 111 | } 112 | 113 | ClassLoader origClzLoader = Thread.currentThread().getContextClassLoader(); 114 | ClassLoader clzLoader = createClassLoader(origClzLoader); 115 | 116 | try { 117 | // set the TCCL before everything else 118 | Thread.currentThread().setContextClassLoader(clzLoader); 119 | 120 | Reader reader = new Reader(swaggerConfig == null ? new OpenAPI() : swaggerConfig.createSwaggerModel()); 121 | 122 | JaxRSScanner reflectiveScanner = new JaxRSScanner(getLog(), resourcePackages, useResourcePackagesChildren); 123 | 124 | Application application = resolveApplication(reflectiveScanner); 125 | reader.setApplication(application); 126 | 127 | OpenAPI swagger = OpenAPISorter.sort(reader.read(reflectiveScanner.classes())); 128 | 129 | if (outputDirectory.mkdirs()) { 130 | getLog().debug("Created output directory " + outputDirectory); 131 | } 132 | 133 | outputFormats.forEach(format -> { 134 | try { 135 | File outputFile = new File(outputDirectory, outputFilename + "." + format.name().toLowerCase()); 136 | format.write(swagger, outputFile, prettyPrint); 137 | if (attachSwaggerArtifact) { 138 | projectHelper.attachArtifact(project, format.name().toLowerCase(), "swagger", outputFile); 139 | } 140 | } catch (IOException e) { 141 | throw new RuntimeException("Unable write " + outputFilename + " document", e); 142 | } 143 | }); 144 | } finally { 145 | // reset the TCCL back to the original class loader 146 | Thread.currentThread().setContextClassLoader(origClzLoader); 147 | } 148 | } 149 | 150 | private Application resolveApplication(JaxRSScanner reflectiveScanner) { 151 | if (applicationClass == null || applicationClass.isEmpty()) { 152 | return reflectiveScanner.applicationInstance(); 153 | } 154 | 155 | Class clazz = ClassUtils.loadClass(applicationClass, Thread.currentThread().getContextClassLoader()); 156 | 157 | if (clazz == null || !Application.class.isAssignableFrom(clazz)) { 158 | getLog().warn("Provided application class does not implement javax.ws.rs.core.Application, skipping"); 159 | return null; 160 | } 161 | 162 | @SuppressWarnings("unchecked") 163 | Class appClazz = (Class)clazz; 164 | return ClassUtils.createInstance(appClazz); 165 | } 166 | 167 | private URLClassLoader createClassLoader(ClassLoader parent) { 168 | try { 169 | Collection dependencies = getDependentClasspathElements(); 170 | URL[] urls = new URL[dependencies.size()]; 171 | int index = 0; 172 | for (String dependency : dependencies) { 173 | urls[index++] = Paths.get(dependency).toUri().toURL(); 174 | } 175 | return new URLClassLoader(urls, parent); 176 | } catch (MalformedURLException e) { 177 | throw new RuntimeException("Unable to create class loader with compiled classes", e); 178 | } catch (DependencyResolutionRequiredException e) { 179 | throw new RuntimeException("Dependency resolution (runtime + compile) is required"); 180 | } 181 | } 182 | 183 | private Collection getDependentClasspathElements() throws DependencyResolutionRequiredException { 184 | Set dependencies = new LinkedHashSet<>(); 185 | dependencies.add(project.getBuild().getOutputDirectory()); 186 | Collection compileClasspathElements = project.getCompileClasspathElements(); 187 | if (compileClasspathElements != null) { 188 | dependencies.addAll(compileClasspathElements); 189 | } 190 | Collection runtimeClasspathElements = project.getRuntimeClasspathElements(); 191 | if (runtimeClasspathElements != null) { 192 | dependencies.addAll(runtimeClasspathElements); 193 | } 194 | return dependencies; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/JaxRSScanner.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | import java.util.Collections; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.Stream; 8 | 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.core.Application; 11 | 12 | import org.apache.maven.plugin.logging.Log; 13 | import org.reflections.Reflections; 14 | import org.reflections.scanners.ResourcesScanner; 15 | import org.reflections.scanners.SubTypesScanner; 16 | import org.reflections.scanners.TypeAnnotationsScanner; 17 | import org.reflections.util.ConfigurationBuilder; 18 | 19 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 20 | 21 | /** 22 | * Scan for classes with {@link Path} annotation or {@link OpenAPIDefinition} 23 | * annotation, and for {@link Application} instances. 24 | */ 25 | class JaxRSScanner { 26 | 27 | private final Log log; 28 | 29 | private final Set resourcePackages; 30 | 31 | private final boolean useResourcePackagesChildren; 32 | 33 | public JaxRSScanner(Log log, Set resourcePackages, Boolean useResourcePackagesChildren) { 34 | this.log = log; 35 | this.resourcePackages = resourcePackages == null ? Collections.emptySet() : new HashSet<>(resourcePackages); 36 | this.useResourcePackagesChildren = useResourcePackagesChildren != null && useResourcePackagesChildren; 37 | } 38 | 39 | Application applicationInstance() { 40 | ConfigurationBuilder config = ConfigurationBuilder 41 | .build(resourcePackages) 42 | .setScanners(new ResourcesScanner(), new TypeAnnotationsScanner(), new SubTypesScanner()); 43 | Reflections reflections = new Reflections(config); 44 | Set> applicationClasses = reflections.getSubTypesOf(Application.class) 45 | .stream() 46 | .filter(this::filterClassByResourcePackages) 47 | .collect(Collectors.toSet()); 48 | if (applicationClasses.isEmpty()) { 49 | return null; 50 | } 51 | if (applicationClasses.size() > 1) { 52 | log.warn("More than one javax.ws.rs.core.Application classes found on the classpath, skipping"); 53 | return null; 54 | } 55 | return ClassUtils.createInstance(applicationClasses.iterator().next()); 56 | } 57 | 58 | Set> classes() { 59 | ConfigurationBuilder config = ConfigurationBuilder 60 | .build(resourcePackages) 61 | .setScanners(new ResourcesScanner(), new TypeAnnotationsScanner(), new SubTypesScanner()); 62 | Reflections reflections = new Reflections(config); 63 | Stream> apiClasses = reflections.getTypesAnnotatedWith(Path.class) 64 | .stream() 65 | .filter(this::filterClassByResourcePackages); 66 | Stream> defClasses = reflections.getTypesAnnotatedWith(OpenAPIDefinition.class) 67 | .stream() 68 | .filter(this::filterClassByResourcePackages); 69 | return Stream.concat(apiClasses, defClasses).collect(Collectors.toSet()); 70 | } 71 | 72 | private boolean filterClassByResourcePackages(Class cls) { 73 | return resourcePackages.isEmpty() 74 | || resourcePackages.contains(cls.getPackage().getName()) 75 | || (useResourcePackagesChildren && resourcePackages.stream().anyMatch(p -> cls.getPackage().getName().startsWith(p))); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/OpenAPISorter.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | import java.util.Map; 4 | import java.util.SortedMap; 5 | import java.util.TreeMap; 6 | 7 | import io.swagger.v3.oas.models.Components; 8 | import io.swagger.v3.oas.models.OpenAPI; 9 | import io.swagger.v3.oas.models.PathItem; 10 | import io.swagger.v3.oas.models.Paths; 11 | import io.swagger.v3.oas.models.media.Schema; 12 | 13 | /** 14 | * Sorter for the contents of an OpenAPI specification. 15 | *

16 | * Sorting the OpenAPI specification solves problems when the output of this plugin is 17 | * committed in a version control system. 18 | *

19 | * The swagger-core library generates non-deterministic output, because reflection operations on 20 | * scanned Resource classes are non-deterministic in the order of methods and fields. 21 | *

22 | * This class and its functionality may be removed if the generation of deterministic output is 23 | * solved in swagger-core. 24 | *

25 | * See https://github.com/swagger-api/swagger-core/issues/3475 26 | * See https://github.com/swagger-api/swagger-core/issues/2775 27 | * See https://github.com/swagger-api/swagger-core/issues/2828 28 | */ 29 | public class OpenAPISorter { 30 | 31 | private OpenAPISorter() { 32 | // No instances 33 | } 34 | 35 | /** 36 | * Sort all the paths and components of the OpenAPI specification, in place. 37 | * @param swagger OpenAPI specification to apply sorting to 38 | * @return the sorted version of the specification 39 | */ 40 | public static OpenAPI sort(OpenAPI swagger) { 41 | swagger.setPaths(sortPaths(swagger.getPaths())); 42 | sortComponents(swagger.getComponents()); 43 | return swagger; 44 | } 45 | 46 | /** 47 | * Sort all the elements of Paths. 48 | */ 49 | private static Paths sortPaths(Paths paths) { 50 | TreeMap sorted = new TreeMap<>(paths); 51 | paths.clear(); 52 | paths.putAll(sorted); 53 | return paths; 54 | } 55 | 56 | /** 57 | * Sort all the elements of Components. 58 | */ 59 | private static void sortComponents(Components components) { 60 | if (components == null) { 61 | return; 62 | } 63 | 64 | components.setSchemas(sortSchemas(components.getSchemas())); 65 | 66 | components.setResponses(createSorted(components.getResponses())); 67 | components.setParameters(createSorted(components.getParameters())); 68 | components.setExamples(createSorted(components.getExamples())); 69 | components.setRequestBodies(createSorted(components.getRequestBodies())); 70 | components.setHeaders(createSorted(components.getHeaders())); 71 | components.setSecuritySchemes(createSorted(components.getSecuritySchemes())); 72 | components.setLinks(createSorted(components.getLinks())); 73 | components.setCallbacks(createSorted(components.getCallbacks())); 74 | components.setExtensions(createSorted(components.getExtensions())); 75 | } 76 | 77 | /** 78 | * Recursively sort all the schemas in the Map. 79 | */ 80 | private static SortedMap sortSchemas(Map schemas) { 81 | if (schemas == null) { 82 | return null; 83 | } 84 | 85 | TreeMap sorted = new TreeMap<>(); 86 | schemas.entrySet().forEach(entry -> { 87 | Schema schema = entry.getValue(); 88 | schema.setProperties(sortSchemas(schema.getProperties())); 89 | sorted.put(entry.getKey(), schema); 90 | }); 91 | 92 | return sorted; 93 | } 94 | 95 | /** 96 | * Created sorted map based on natural key order. 97 | */ 98 | private static SortedMap createSorted(Map map) { 99 | return map == null ? null : new TreeMap<>(map); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/OutputFormat.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.SerializationFeature; 8 | import io.openapitools.swagger.config.SwaggerServerVariable; 9 | import io.swagger.v3.core.util.Json; 10 | import io.swagger.v3.core.util.Yaml; 11 | import io.swagger.v3.oas.models.OpenAPI; 12 | import io.swagger.v3.oas.models.servers.ServerVariable; 13 | 14 | /** 15 | * Supported output formats. 16 | */ 17 | public enum OutputFormat { 18 | 19 | JSON(new JSONWriter()), 20 | YAML(new YAMLWriter()); 21 | 22 | private final SwaggerWriter writer; 23 | 24 | OutputFormat(SwaggerWriter writer) { 25 | this.writer = writer; 26 | } 27 | 28 | public void write(OpenAPI swagger, File file, boolean prettyPrint) throws IOException { 29 | writer.write(swagger, file, prettyPrint); 30 | } 31 | 32 | /** 33 | * Interface defining requirements for being able to write out Swagger instance to file. 34 | */ 35 | @FunctionalInterface 36 | interface SwaggerWriter { 37 | void write(OpenAPI swagger, File file, boolean prettyPrint) throws IOException; 38 | } 39 | 40 | /** 41 | * As the Maven plugin plugin does not support lambdas properly a real implementation is needed. 42 | */ 43 | static class JSONWriter implements SwaggerWriter { 44 | 45 | @Override 46 | public void write(OpenAPI swagger, File file, boolean prettyPrint) throws IOException { 47 | ObjectMapper mapper = Json.mapper(); 48 | mapper.addMixIn(ServerVariable.class, SwaggerServerVariable.ServerVariableMixin.class); 49 | if (prettyPrint) { 50 | mapper.enable(SerializationFeature.INDENT_OUTPUT); 51 | } 52 | mapper.writeValue(file, swagger); 53 | } 54 | } 55 | 56 | /** 57 | * As the Maven plugin plugin does not support lambdas properly a real implementation is needed. 58 | */ 59 | static class YAMLWriter implements SwaggerWriter { 60 | 61 | @Override 62 | public void write(OpenAPI swagger, File file, boolean prettyPrint) throws IOException { 63 | ObjectMapper mapper = Yaml.mapper(); 64 | mapper.addMixIn(ServerVariable.class, SwaggerServerVariable.ServerVariableMixin.class); 65 | mapper.writeValue(file, swagger); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerComponents.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import java.util.Map; 4 | 5 | import org.apache.maven.plugins.annotations.Parameter; 6 | 7 | import io.swagger.v3.oas.models.Components; 8 | 9 | public class SwaggerComponents { 10 | 11 | /** 12 | * Security schemes (under Comtonents) 13 | */ 14 | @Parameter 15 | private Map securitySchemes; 16 | 17 | // TODO: implement schemas, responses, ... from 18 | // https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#componentsObject 19 | 20 | public Components createComponentsModel() { 21 | Components components = new Components(); 22 | 23 | if (securitySchemes != null && !securitySchemes.isEmpty()) { 24 | securitySchemes.entrySet().forEach(s -> components.addSecuritySchemes(s.getKey(), s.getValue().createSecuritySchemaModel())); 25 | } 26 | 27 | return components; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import io.swagger.v3.oas.annotations.ExternalDocumentation; 4 | import io.swagger.v3.oas.annotations.Parameters; 5 | import io.swagger.v3.oas.models.OpenAPI; 6 | import io.swagger.v3.oas.models.info.Info; 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.nio.file.Files; 10 | import java.util.Collections; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.stream.Collectors; 14 | import org.apache.maven.plugins.annotations.Parameter; 15 | 16 | /** 17 | * Configuring Swagger in compliance with the way the com.github.kongchen 18 | * Swagger plugin does it. 19 | */ 20 | public class SwaggerConfig { 21 | 22 | /** 23 | * REQUIRED. Provides metadata about the API. The metadata MAY be used by 24 | * tooling as required. 25 | * 26 | * This might be overridden by ReaderListener or SwaggerDefinition annotation. 27 | */ 28 | @Parameter 29 | private SwaggerInfo info; 30 | 31 | /** 32 | * Convenience for reading the informational description from file instead of 33 | * embedding it. 34 | */ 35 | @Parameter 36 | private File descriptionFile; 37 | 38 | /** 39 | * An array of Server Objects, which provide connectivity information to a 40 | * target server. If the servers property is not provided, or is an empty array, 41 | * the default value would be a Server Object with a url value of /. 42 | */ 43 | @Parameter 44 | private List servers = Collections.emptyList(); 45 | 46 | /** 47 | * An element to hold various schemas for the specification. 48 | */ 49 | @Parameter 50 | private SwaggerComponents components; 51 | 52 | /** 53 | * A declaration of which security mechanisms can be used across the API. The 54 | * list of values includes alternative security requirement objects that can be 55 | * used. Only one of the security requirement objects need to be satisfied to 56 | * authorize a request. Individual operations can override this definition. 57 | */ 58 | @Parameter 59 | private List securityRequirements = Collections.emptyList();; 60 | 61 | /** 62 | * A list of tags used by the specification with additional metadata. The order 63 | * of the tags can be used to reflect on their order by the parsing tools. Not 64 | * all tags that are used by the Operation Object must be declared. The tags 65 | * that are not declared MAY be organized randomly or based on the tools' logic. 66 | * Each tag name in the list MUST be unique. 67 | */ 68 | @Parameter 69 | private List tags = Collections.emptyList();; 70 | 71 | /** 72 | * Additional external documentation. 73 | */ 74 | @Parameter 75 | private SwaggerExternalDoc externalDoc; 76 | 77 | /** 78 | * Providing extension attributes to the OpenAPI spec. 79 | */ 80 | @Parameter 81 | private Map extensions = Collections.emptyMap(); 82 | 83 | public OpenAPI createSwaggerModel() { 84 | OpenAPI spec = new OpenAPI(); 85 | 86 | if (info != null) { 87 | spec.setInfo(info.createInfoModel()); 88 | } 89 | 90 | if (descriptionFile != null) { 91 | if (spec.getInfo() == null) { 92 | spec.setInfo(new Info()); 93 | } 94 | try { 95 | spec.getInfo().setDescription( 96 | Files.readAllLines(descriptionFile.toPath()).stream().collect(Collectors.joining("\n"))); 97 | } catch (IOException e) { 98 | throw new RuntimeException("Unable to read descriptor file " + descriptionFile, e); 99 | } 100 | } 101 | 102 | if (components != null) { 103 | spec.setComponents(components.createComponentsModel()); 104 | } 105 | 106 | if (externalDoc != null) { 107 | spec.setExternalDocs(externalDoc.createExternalDocModel()); 108 | } 109 | 110 | spec.setExtensions(extensions); 111 | servers.forEach(s -> spec.addServersItem(s.createServerModel())); 112 | securityRequirements.forEach(s -> spec.addSecurityItem(s.createSecurityModel())); 113 | tags.forEach(t -> spec.addTagsItem(t.createTagModel())); 114 | 115 | return spec; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerContact.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import io.swagger.v3.oas.models.info.Contact; 4 | 5 | import java.util.Collections; 6 | import java.util.Map; 7 | 8 | import org.apache.maven.plugins.annotations.Parameter; 9 | 10 | /** 11 | * Configuring Swagger contact properties. 12 | */ 13 | public class SwaggerContact { 14 | 15 | /** 16 | * The identifying name of the contact person/organization. 17 | */ 18 | @Parameter 19 | private String name; 20 | 21 | /** 22 | * The URL pointing to the contact information. MUST be in the format of a URL. 23 | */ 24 | @Parameter 25 | private String url; 26 | 27 | /** 28 | * The email address of the contact person/organization. MUST be in the format of an email address. 29 | */ 30 | @Parameter 31 | private String email; 32 | 33 | @Parameter 34 | private Map extensions = Collections.emptyMap(); 35 | 36 | public Contact createContactModel() { 37 | Contact contact = new Contact(); 38 | 39 | if (name != null) { 40 | contact.setName(name); 41 | } 42 | 43 | if (url != null) { 44 | contact.setUrl(url); 45 | } 46 | 47 | if (email != null) { 48 | contact.setEmail(email); 49 | } 50 | 51 | contact.setExtensions(extensions); 52 | 53 | return contact; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerExternalDoc.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import java.util.Collections; 4 | import java.util.Map; 5 | 6 | import org.apache.maven.plugins.annotations.Parameter; 7 | 8 | import io.swagger.v3.oas.models.ExternalDocumentation; 9 | 10 | public class SwaggerExternalDoc { 11 | 12 | /** 13 | * A short description of the target documentation. CommonMark syntax MAY be 14 | * used for rich text representation. 15 | */ 16 | @Parameter 17 | private String description; 18 | 19 | /** 20 | * REQUIRED. The URL for the target documentation. Value MUST be in the format 21 | * of a URL. 22 | */ 23 | @Parameter(required = true) 24 | private String url; 25 | 26 | @Parameter 27 | private Map extensions = Collections.emptyMap(); 28 | 29 | public ExternalDocumentation createExternalDocModel() { 30 | ExternalDocumentation externalDoc = new ExternalDocumentation(); 31 | 32 | if (description != null) { 33 | externalDoc.setDescription(description); 34 | } 35 | 36 | if (url != null) { 37 | externalDoc.setUrl(url); 38 | } 39 | 40 | externalDoc.setExtensions(extensions); 41 | 42 | return externalDoc; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerFlows.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import java.util.Collections; 4 | import java.util.Map; 5 | 6 | import io.swagger.v3.oas.annotations.Parameter; 7 | import io.swagger.v3.oas.models.security.OAuthFlow; 8 | import io.swagger.v3.oas.models.security.OAuthFlows; 9 | import io.swagger.v3.oas.models.security.Scopes; 10 | 11 | public class SwaggerFlows { 12 | 13 | /** 14 | * Configuration for the OAuth Implicit flow 15 | */ 16 | @Parameter 17 | private Entry implicit; 18 | 19 | /** 20 | * Configuration for the OAuth Resource Owner Password flow 21 | */ 22 | @Parameter 23 | private Entry password; 24 | 25 | /** 26 | * Configuration for the OAuth Client Credentials flow. Previously called 27 | * application in OpenAPI 2.0. 28 | */ 29 | @Parameter 30 | private Entry clientCredentials; 31 | 32 | /** 33 | * Configuration for the OAuth Authorization Code flow. Previously called 34 | * accessCode in OpenAPI 2.0. 35 | */ 36 | @Parameter 37 | private Entry authorizationCode; 38 | 39 | @Parameter 40 | private Map extensions = Collections.emptyMap(); 41 | 42 | public OAuthFlows createOAuthFlowsModel() { 43 | OAuthFlows flows = new OAuthFlows(); 44 | if (implicit != null) { 45 | flows.setImplicit(implicit.toOAuthFlowModel()); 46 | } 47 | if (password != null) { 48 | flows.setPassword(password.toOAuthFlowModel()); 49 | } 50 | if (clientCredentials != null) { 51 | flows.setClientCredentials(clientCredentials.toOAuthFlowModel()); 52 | } 53 | if (authorizationCode != null) { 54 | flows.setAuthorizationCode(authorizationCode.toOAuthFlowModel()); 55 | } 56 | flows.setExtensions(extensions); 57 | return flows; 58 | } 59 | 60 | public static class Entry { 61 | /** 62 | * For implicit/authorizationCode flows: REQUIRED. The authorization URL to be used for this flow. This MUST be in the form of a URL. 63 | */ 64 | @Parameter 65 | private String authorizationUrl; 66 | 67 | /** 68 | * For password/clientCredentials/AuthorizationCode flows: REQUIRED. The token URL to be used for this flow. This MUST be in the form of a URL. 69 | */ 70 | @Parameter 71 | private String tokenUrl; 72 | 73 | /** 74 | * The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. 75 | */ 76 | @Parameter 77 | private String refreshUrl; 78 | 79 | /** 80 | * REQUIRED. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. 81 | */ 82 | @Parameter(required = true) 83 | private Map scopes = Collections.emptyMap(); 84 | 85 | @Parameter 86 | private Map extensions = Collections.emptyMap(); 87 | 88 | public OAuthFlow toOAuthFlowModel() { 89 | OAuthFlow flow = new OAuthFlow(); 90 | 91 | flow.setAuthorizationUrl(authorizationUrl); 92 | flow.setTokenUrl(tokenUrl); 93 | flow.setRefreshUrl(refreshUrl); 94 | if (scopes != null && !scopes.isEmpty()) { 95 | Scopes ss = new Scopes(); 96 | scopes.entrySet().forEach(s -> ss.addString(s.getKey(), s.getValue())); 97 | flow.setScopes(ss); 98 | } 99 | 100 | if (extensions != null && !extensions.isEmpty()) { 101 | flow.setExtensions(extensions); 102 | } 103 | return flow; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerInfo.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import io.swagger.v3.oas.models.info.Info; 4 | import java.util.Map; 5 | import org.apache.maven.plugins.annotations.Parameter; 6 | 7 | /** 8 | * Configuring the Swagger info properties. 9 | */ 10 | public class SwaggerInfo { 11 | 12 | /** 13 | * REQUIRED. The title of the application. 14 | */ 15 | @Parameter(required = true) 16 | private String title; 17 | 18 | /** 19 | * REQUIRED. The version of the OpenAPI document (which is distinct from the 20 | * OpenAPI Specification version or the API implementation version). 21 | */ 22 | @Parameter(required = true) 23 | private String version; 24 | 25 | /** 26 | * A short description of the application. CommonMark syntax MAY be used for 27 | * rich text representation. 28 | */ 29 | @Parameter 30 | private String description; 31 | 32 | /** 33 | * A URL to the Terms of Service for the API. MUST be in the format of a URL. 34 | */ 35 | @Parameter 36 | private String termsOfService; 37 | 38 | /** 39 | * The contact information for the exposed API. 40 | */ 41 | @Parameter 42 | private SwaggerContact contact; 43 | 44 | /** 45 | * The license information for the exposed API. 46 | */ 47 | @Parameter 48 | private SwaggerLicense license; 49 | 50 | @Parameter 51 | private Map extensions; 52 | 53 | public Info createInfoModel() { 54 | Info info = new Info(); 55 | 56 | if (title != null) { 57 | info.setTitle(title); 58 | } 59 | 60 | if (version != null) { 61 | info.setVersion(version); 62 | } 63 | 64 | if (description != null) { 65 | info.setDescription(description); 66 | } 67 | 68 | if (termsOfService != null) { 69 | info.setTermsOfService(termsOfService); 70 | } 71 | 72 | if (contact != null) { 73 | info.setContact(contact.createContactModel()); 74 | } 75 | 76 | if (license != null) { 77 | info.setLicense(license.createLicenseModel()); 78 | } 79 | 80 | if (extensions != null && !extensions.isEmpty()) { 81 | info.setExtensions(extensions); 82 | } 83 | 84 | return info; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerLicense.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import io.swagger.v3.oas.models.info.License; 4 | 5 | import java.util.Collections; 6 | import java.util.Map; 7 | 8 | import org.apache.maven.plugins.annotations.Parameter; 9 | 10 | /** 11 | * Configuring Swagger license. 12 | */ 13 | public class SwaggerLicense { 14 | 15 | /** 16 | * REQUIRED. The license name used for the API. 17 | */ 18 | @Parameter(required = true) 19 | private String name; 20 | 21 | /** 22 | * A URL to the license used for the API. MUST be in the format of a URL. 23 | */ 24 | @Parameter 25 | private String url; 26 | 27 | @Parameter 28 | private Map extensions = Collections.emptyMap(); 29 | 30 | public License createLicenseModel() { 31 | License license = new License(); 32 | 33 | if (name != null) { 34 | license.setName(name); 35 | } 36 | 37 | if (url != null) { 38 | license.setUrl(url); 39 | } 40 | 41 | license.setExtensions(extensions); 42 | 43 | return license; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerSecurityRequirement.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.apache.maven.plugins.annotations.Parameter; 7 | 8 | import io.swagger.v3.oas.models.security.SecurityRequirement; 9 | 10 | public class SwaggerSecurityRequirement { 11 | 12 | /** 13 | * Each name MUST correspond to a security scheme which is declared in the 14 | * Security Schemes under the Components Object. If the security scheme is of 15 | * type "oauth2" or "openIdConnect", then the value is a list of scope names 16 | * required for the execution. For other security scheme types, the array MUST 17 | * be empty. 18 | */ 19 | @Parameter 20 | private List entries = Collections.emptyList(); 21 | 22 | public SecurityRequirement createSecurityModel() { 23 | if (entries == null || entries.isEmpty()) { 24 | return null; 25 | } 26 | 27 | SecurityRequirement securityReq = new SecurityRequirement(); 28 | entries.forEach(e -> securityReq.addList(e.name, e.list)); 29 | return securityReq; 30 | } 31 | 32 | public static class Entry { 33 | 34 | @Parameter(required = true) 35 | private String name; 36 | 37 | @Parameter 38 | private List list = Collections.emptyList(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerSecurityScheme.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import java.util.Map; 4 | 5 | import org.apache.maven.plugins.annotations.Parameter; 6 | 7 | import io.swagger.v3.oas.models.security.SecurityScheme; 8 | import io.swagger.v3.oas.models.security.SecurityScheme.In; 9 | import io.swagger.v3.oas.models.security.SecurityScheme.Type; 10 | 11 | public class SwaggerSecurityScheme { 12 | 13 | /** 14 | * REQUIRED. The type of the security scheme. Valid values are "apiKey", "http", 15 | * "oauth2", "openIdConnect". 16 | */ 17 | @Parameter 18 | private String type; 19 | 20 | /** 21 | * A short description for security scheme. CommonMark syntax MAY be used for 22 | * rich text representation. 23 | */ 24 | @Parameter 25 | private String description; 26 | 27 | /** 28 | * If type is apiKey: REQUIRED. The name of the header, query or cookie 29 | * parameter to be used. 30 | */ 31 | @Parameter 32 | private String name; 33 | 34 | /** 35 | * If type is apiKey: REQUIRED. The location of the API key. Valid values are 36 | * "query", "header" or "cookie". 37 | */ 38 | @Parameter 39 | private String in; 40 | 41 | /** 42 | * If type is http: REQUIRED. The name of the HTTP Authorization scheme to be 43 | * used in the Authorization header as defined in RFC7235. 44 | */ 45 | @Parameter 46 | private String scheme; 47 | 48 | /** 49 | * If type is http/"bearer": A hint to the client to identify how the bearer 50 | * token is formatted. Bearer tokens are usually generated by an authorization 51 | * server, so this information is primarily for documentation purposes. 52 | */ 53 | @Parameter 54 | private String bearerFormat; 55 | 56 | /** 57 | * If type is oauth2: REQUIRED. An object containing configuration information 58 | * for the flow types supported. 59 | */ 60 | @Parameter 61 | private SwaggerFlows flows; 62 | 63 | /** 64 | * If type is openIdConnect: REQUIRED. OpenId Connect URL to discover OAuth2 65 | * configuration values. This MUST be in the form of a URL. 66 | */ 67 | @Parameter 68 | private String openIdConnectUrl; 69 | 70 | @Parameter 71 | private Map extensions; 72 | 73 | @Parameter 74 | private String $ref; 75 | 76 | public SecurityScheme createSecuritySchemaModel() { 77 | SecurityScheme securityScheme = new SecurityScheme(); 78 | 79 | if (type != null) { 80 | securityScheme.setType(Type.valueOf(type.toUpperCase())); 81 | } 82 | securityScheme.setDescription(description); 83 | securityScheme.setName(name); 84 | if (in != null) { 85 | securityScheme.setIn(In.valueOf(in.toUpperCase())); 86 | } 87 | securityScheme.setScheme(scheme); 88 | securityScheme.setBearerFormat(bearerFormat); 89 | if (flows != null) { 90 | securityScheme.setFlows(flows.createOAuthFlowsModel()); 91 | } 92 | securityScheme.setOpenIdConnectUrl(openIdConnectUrl); 93 | 94 | if (extensions != null && !extensions.isEmpty()) { 95 | securityScheme.setExtensions(extensions); 96 | } 97 | 98 | // Alternative to setting all above properties: reference to other component 99 | securityScheme.set$ref($ref); 100 | 101 | return securityScheme; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerServer.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import io.swagger.v3.oas.models.servers.Server; 4 | import io.swagger.v3.oas.models.servers.ServerVariables; 5 | 6 | import java.util.Collections; 7 | import java.util.Map; 8 | 9 | import org.apache.maven.plugins.annotations.Parameter; 10 | 11 | public class SwaggerServer { 12 | 13 | /** 14 | * REQUIRED. A URL to the target host. This URL supports Server Variables and 15 | * MAY be relative, to indicate that the host location is relative to the 16 | * location where the OpenAPI document is being served. Variable substitutions 17 | * will be made when a variable is named in {brackets}. 18 | */ 19 | @Parameter(required = true) 20 | private String url; 21 | 22 | /** 23 | * An optional string describing the host designated by the URL. CommonMark 24 | * syntax MAY be used for rich text representation. 25 | */ 26 | @Parameter 27 | private String description; 28 | 29 | /** 30 | * A map between a variable name and its value. The value is used for 31 | * substitution in the server's URL template. 32 | */ 33 | @Parameter 34 | private Map variables = Collections.emptyMap(); 35 | 36 | @Parameter 37 | private Map extensions = Collections.emptyMap(); 38 | 39 | public Server createServerModel() { 40 | Server server = new Server(); 41 | server.setUrl(url); 42 | server.setDescription(description); 43 | 44 | if (variables != null && !variables.isEmpty()) { 45 | ServerVariables vs = new ServerVariables(); 46 | variables.entrySet() 47 | .forEach(v -> vs.addServerVariable(v.getKey(), v.getValue().createServerVariableModel())); 48 | server.setVariables(vs); 49 | } 50 | 51 | server.setExtensions(extensions); 52 | 53 | return server; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerServerVariable.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 8 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 9 | import io.swagger.v3.oas.models.servers.ServerVariable; 10 | import org.apache.maven.plugins.annotations.Parameter; 11 | 12 | public class SwaggerServerVariable { 13 | 14 | /** 15 | * REQUIRED. The default value to use for substitution, and to send, if an 16 | * alternate value is not supplied. Unlike the Schema Object's default, this 17 | * value MUST be provided by the consumer. 18 | */ 19 | @Parameter(required = true) 20 | private String defaultValue; 21 | 22 | /** 23 | * An enumeration of string values to be used if the substitution options are 24 | * from a limited set. 25 | */ 26 | @Parameter 27 | private List enumValues = Collections.emptyList(); 28 | 29 | /** 30 | * An optional description for the server variable. CommonMark syntax MAY be 31 | * used for rich text representation. 32 | */ 33 | @Parameter 34 | private String description; 35 | 36 | @Parameter 37 | private Map extensions; 38 | 39 | public ServerVariable createServerVariableModel() { 40 | ServerVariable serverVar = new ServerVariable(); 41 | 42 | serverVar.setDefault(defaultValue); 43 | if (enumValues != null && !enumValues.isEmpty()) { 44 | serverVar.setEnum(enumValues); 45 | } 46 | serverVar.setDescription(description); 47 | 48 | if (extensions != null && !extensions.isEmpty()) { 49 | serverVar.setExtensions(extensions); 50 | } 51 | 52 | return serverVar; 53 | } 54 | 55 | @JsonPropertyOrder({"description", "default", "enum"}) 56 | public static abstract class ServerVariableMixin { 57 | @JsonAnyGetter 58 | public abstract Map getExtensions(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/io/openapitools/swagger/config/SwaggerTag.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.config; 2 | 3 | import java.util.Map; 4 | 5 | import org.apache.maven.plugins.annotations.Parameter; 6 | 7 | import io.swagger.v3.oas.models.tags.Tag; 8 | 9 | public class SwaggerTag { 10 | 11 | /** 12 | * REQUIRED. The name of the tag. 13 | */ 14 | @Parameter(required = true) 15 | private String name; 16 | 17 | /** 18 | * A short description for the tag. CommonMark syntax MAY be used for rich text representation. 19 | */ 20 | @Parameter 21 | private String description; 22 | 23 | /** 24 | * Additional external documentation for this tag. 25 | */ 26 | @Parameter 27 | private SwaggerExternalDoc externalDoc; 28 | 29 | @Parameter 30 | private Map extensions; 31 | 32 | public Tag createTagModel(){ 33 | Tag tag = new Tag(); 34 | 35 | tag.setName(name); 36 | tag.setDescription(description); 37 | 38 | if (externalDoc != null) { 39 | tag.setExternalDocs(externalDoc.createExternalDocModel()); 40 | } 41 | 42 | if (extensions != null && !extensions.isEmpty()) { 43 | tag.setExtensions(extensions); 44 | } 45 | 46 | return tag; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/GenerateMojoIT.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.charset.StandardCharsets; 6 | import java.nio.file.FileVisitResult; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.nio.file.Paths; 10 | import java.nio.file.SimpleFileVisitor; 11 | import java.nio.file.attribute.BasicFileAttributes; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | import com.fasterxml.jackson.databind.ObjectMapper; 16 | import io.swagger.v3.core.util.Json; 17 | import io.swagger.v3.core.util.Yaml; 18 | import io.swagger.v3.oas.models.OpenAPI; 19 | import org.apache.maven.plugin.Mojo; 20 | import org.apache.maven.plugin.testing.MojoRule; 21 | import org.junit.Assert; 22 | import org.junit.Rule; 23 | import org.junit.Test; 24 | 25 | public class GenerateMojoIT { 26 | 27 | @Rule 28 | public MojoRule rule = new MojoRule(); 29 | 30 | private void assertJsonEquals(Path expectedJson, Path generatedJson) throws IOException { 31 | assertOpenApiEquals(Json.mapper(), expectedJson, generatedJson); 32 | assertFileContentEquals(expectedJson, generatedJson); 33 | } 34 | 35 | private void assertYamlEquals(Path expectedYaml, Path generatedYaml) throws IOException { 36 | assertOpenApiEquals(Yaml.mapper(), expectedYaml, generatedYaml); 37 | assertFileContentEquals(expectedYaml, generatedYaml); 38 | } 39 | 40 | private void assertFileContentEquals(Path expected, Path generated) { 41 | try { 42 | Assert.assertEquals(String.join("\n", Files.readAllLines(expected, StandardCharsets.UTF_8)), String.join("\n", Files.readAllLines(generated, StandardCharsets.UTF_8))); 43 | } catch (IOException e) { 44 | Assert.fail(); 45 | } 46 | } 47 | 48 | private void assertOpenApiEquals(ObjectMapper mapper, Path expected, Path generated) throws IOException { 49 | OpenAPI expectedAPI = mapper.readValue(expected.toFile(), OpenAPI.class); 50 | OpenAPI generatedAPI = mapper.readValue(generated.toFile(), OpenAPI.class); 51 | 52 | // OpenAPI.equals() performs a deep equal check of all its properties 53 | Assert.assertEquals(expectedAPI, generatedAPI); 54 | } 55 | 56 | /** 57 | * Tests the generated Swagger specifications based on the given method parameters. 58 | * 59 | * @param folder The base folder of the expected output. 60 | * @param basename The basename for the generated Swagger specifications. 61 | * @param pom The name of the POM file to be used for the test. 62 | * @param prettyPrinted If true, the generated JSON Swagger specification should be pretty-printed. 63 | * @param outputFormats The output formats that should be generated and checked. 64 | * 65 | * @throws Exception If a JSON parsing or file-read exception happens. 66 | */ 67 | private void testGenerate(String folder, String basename, String pom, boolean prettyPrinted, OutputFormat... outputFormats) 68 | throws Exception { 69 | 70 | Path output = Paths.get(folder); 71 | if (Files.exists(output)) { 72 | Files.walkFileTree(output, new DeleteVisitor()); 73 | } 74 | 75 | Mojo mojo = rule.lookupMojo("generate", new File("src/test/resources/" + pom)); 76 | mojo.execute(); 77 | 78 | List formats = Arrays.asList(outputFormats); 79 | if (formats.contains(OutputFormat.JSON)) { 80 | Path expectedJson = Paths.get("src/test/resources/expectedOutput", folder, basename + ".json"); 81 | Path generatedJson = Paths.get("target", folder, basename + ".json"); 82 | assertJsonEquals(expectedJson, generatedJson); 83 | 84 | // We test the indentation by simply checking that the generated JSON contains 2 spaces 85 | String json = new String(Files.readAllBytes(generatedJson), StandardCharsets.UTF_8); 86 | Assert.assertEquals(prettyPrinted, json.contains(" ")); 87 | } 88 | 89 | if (formats.contains(OutputFormat.YAML)) { 90 | Path expectedYaml = Paths.get("src/test/resources/expectedOutput", folder, basename + ".yaml"); 91 | Path generatedYaml = Paths.get("target", folder, basename + ".yaml"); 92 | assertYamlEquals(expectedYaml, generatedYaml); 93 | } 94 | } 95 | 96 | @Test 97 | public void testGenerateApi() throws Exception { 98 | testGenerate("api", "swagger", "generate-mojo-pom.xml", false, OutputFormat.JSON, OutputFormat.YAML); 99 | } 100 | 101 | @Test 102 | public void testGenerateDefaults() throws Exception { 103 | testGenerate("default", "swagger", "generate-mojo-defaults-pom.xml", false, OutputFormat.JSON); 104 | } 105 | 106 | @Test 107 | public void testGenerateApplicationClass() throws Exception { 108 | testGenerate("application", "swagger", "generate-mojo-application.xml", false, OutputFormat.JSON); 109 | } 110 | 111 | @Test 112 | public void testGenerateApplicationClassByScanning() throws Exception { 113 | testGenerate("application", "swagger", "generate-mojo-application-scan.xml", false, OutputFormat.JSON); 114 | } 115 | 116 | @Test 117 | public void testGenerateFull() throws Exception { 118 | testGenerate("full", "open-api", "generate-mojo-full-pom.xml", false, OutputFormat.JSON, OutputFormat.YAML); 119 | } 120 | 121 | @Test 122 | public void testGenerateFullNoFileName() throws Exception { 123 | testGenerate("semifull", "swagger", "generate-mojo-full-nofilename-pom.xml", false, OutputFormat.JSON, OutputFormat.YAML); 124 | } 125 | 126 | @Test 127 | public void testGenerateFullPretty() throws Exception { 128 | testGenerate("fullpretty", "open-api", "generate-mojo-full-pretty-pom.xml", true, OutputFormat.JSON, OutputFormat.YAML); 129 | } 130 | 131 | @Test 132 | public void testGenerateRecursive() throws Exception { 133 | testGenerate("recursive", "swagger", "generate-mojo-recursive-pom.xml", true, OutputFormat.JSON); 134 | } 135 | 136 | private static class DeleteVisitor extends SimpleFileVisitor { 137 | @Override 138 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 139 | Files.delete(file); 140 | return FileVisitResult.CONTINUE; 141 | } 142 | 143 | @Override 144 | public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { 145 | Files.delete(dir); 146 | return FileVisitResult.CONTINUE; 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/MavenProjectStub.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | import org.apache.maven.model.Build; 4 | 5 | public class MavenProjectStub extends org.apache.maven.plugin.testing.stubs.MavenProjectStub { 6 | 7 | public MavenProjectStub() { 8 | Build b = new Build(); 9 | b.setOutputDirectory("target/test-classes"); 10 | setBuild(b); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/OpenApiSorterTest.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger; 2 | 3 | import io.swagger.v3.oas.models.Components; 4 | import io.swagger.v3.oas.models.OpenAPI; 5 | import io.swagger.v3.oas.models.PathItem; 6 | import io.swagger.v3.oas.models.Paths; 7 | import io.swagger.v3.oas.models.callbacks.Callback; 8 | import io.swagger.v3.oas.models.examples.Example; 9 | import io.swagger.v3.oas.models.headers.Header; 10 | import io.swagger.v3.oas.models.links.Link; 11 | import io.swagger.v3.oas.models.media.ObjectSchema; 12 | import io.swagger.v3.oas.models.media.StringSchema; 13 | import io.swagger.v3.oas.models.parameters.Parameter; 14 | import io.swagger.v3.oas.models.parameters.RequestBody; 15 | import io.swagger.v3.oas.models.responses.ApiResponse; 16 | import io.swagger.v3.oas.models.security.SecurityScheme; 17 | import org.junit.Test; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | public class OpenApiSorterTest { 22 | 23 | @Test 24 | public void testSort() { 25 | ObjectSchema schema1 = new ObjectSchema(); 26 | schema1.addProperties("s1-2", new StringSchema()); 27 | schema1.addProperties("s1-1", new StringSchema()); 28 | 29 | ObjectSchema schema2 = new ObjectSchema(); 30 | schema2.addProperties("s2-2", new StringSchema()); 31 | schema2.addProperties("s2-1", new StringSchema()); 32 | 33 | Components components = new Components() 34 | .addSchemas("s2", schema2) 35 | .addSchemas("s1", schema1) 36 | .addResponses("k2", new ApiResponse()) 37 | .addResponses("k1", new ApiResponse()) 38 | .addParameters("k2", new Parameter()) 39 | .addParameters("k1", new Parameter()) 40 | .addExamples("k2", new Example()) 41 | .addExamples("k1", new Example()) 42 | .addRequestBodies("k2", new RequestBody()) 43 | .addRequestBodies("k1", new RequestBody()) 44 | .addHeaders("k2", new Header()) 45 | .addHeaders("k1", new Header()) 46 | .addSecuritySchemes("k2", new SecurityScheme()) 47 | .addSecuritySchemes("k1", new SecurityScheme()) 48 | .addLinks("k2", new Link()) 49 | .addLinks("k1", new Link()) 50 | .addCallbacks("k2", new Callback()) 51 | .addCallbacks("k1", new Callback()); 52 | 53 | Paths paths = new Paths() 54 | .addPathItem("p2", new PathItem()) 55 | .addPathItem("p1", new PathItem()); 56 | 57 | OpenAPI api = new OpenAPI() 58 | .components(components) 59 | .paths(paths); 60 | 61 | api = OpenAPISorter.sort(api); 62 | 63 | assertEquals("s1-1", api.getComponents().getSchemas() 64 | .values().stream() 65 | .findFirst().get().getProperties() 66 | .keySet().stream().findFirst().get()); 67 | assertEquals("s2-1", api.getComponents().getSchemas() 68 | .values().stream() 69 | .skip(1).findFirst().get().getProperties() 70 | .keySet().stream().findFirst().get()); 71 | assertEquals("k1", api.getComponents().getResponses().keySet().stream().findFirst().get()); 72 | assertEquals("k1", api.getComponents().getParameters().keySet().stream().findFirst().get()); 73 | assertEquals("k1", api.getComponents().getExamples().keySet().stream().findFirst().get()); 74 | assertEquals("k1", api.getComponents().getRequestBodies().keySet().stream().findFirst().get()); 75 | assertEquals("k1", api.getComponents().getHeaders().keySet().stream().findFirst().get()); 76 | assertEquals("k1", api.getComponents().getSecuritySchemes().keySet().stream().findFirst().get()); 77 | assertEquals("k1", api.getComponents().getLinks().keySet().stream().findFirst().get()); 78 | assertEquals("k1", api.getComponents().getCallbacks().keySet().stream().findFirst().get()); 79 | assertEquals("p1", api.getPaths().keySet().stream().findFirst().get()); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/AccountServiceExposure.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example; 2 | 3 | import io.openapitools.swagger.example.model.AccountUpdateRepresentation; 4 | import io.swagger.v3.oas.annotations.Hidden; 5 | import io.swagger.v3.oas.annotations.Operation; 6 | import io.swagger.v3.oas.annotations.responses.ApiResponse; 7 | import javax.validation.Valid; 8 | import javax.validation.constraints.Pattern; 9 | import javax.ws.rs.Consumes; 10 | import javax.ws.rs.GET; 11 | import javax.ws.rs.PUT; 12 | import javax.ws.rs.Path; 13 | import javax.ws.rs.PathParam; 14 | import javax.ws.rs.Produces; 15 | import javax.ws.rs.core.Context; 16 | import javax.ws.rs.core.MediaType; 17 | import javax.ws.rs.core.Request; 18 | import javax.ws.rs.core.Response; 19 | import javax.ws.rs.core.UriInfo; 20 | 21 | /** 22 | * Exposing account as REST service. 23 | */ 24 | @Path("/accounts") 25 | public class AccountServiceExposure { 26 | 27 | @GET 28 | @Produces({"application/hal+json"}) 29 | public Response list(@Context UriInfo uriInfo, @Context Request request) { 30 | return Response.ok().build(); 31 | } 32 | 33 | @GET 34 | @Path("{regNo}-{accountNo}") 35 | @Produces({"application/hal+json"}) 36 | @Operation(description = "Get single account", 37 | responses = {@ApiResponse(responseCode = "404", description = "No account found.")}) 38 | public Response get(@PathParam("regNo") @Pattern(regexp = "^[0-9]{4}$") String regNo, 39 | @PathParam("accountNo") @Pattern(regexp = "^[0-9]+$") String accountNo, 40 | @Context UriInfo uriInfo, @Context Request request) { 41 | return Response.ok().build(); 42 | } 43 | 44 | @GET 45 | @Path("{regNo}-{accountNo}") 46 | @Produces({"application/hal+json;v=1"}) 47 | @Hidden 48 | public Response getV1() { 49 | return null; 50 | } 51 | 52 | @PUT 53 | @Path("{regNo}-{accountNo}") 54 | @Produces({"application/hal+json"}) 55 | @Consumes(MediaType.APPLICATION_JSON) 56 | @Operation(description = "Create new or update existing account", 57 | responses = @ApiResponse(responseCode = "404", description = "No updating possible")) 58 | public Response createOrUpdate(@PathParam("regNo") @Pattern(regexp = "^[0-9]{4}$") String regNo, 59 | @PathParam("accountNo") @Pattern(regexp = "^[0-9]+$") String accountNo, 60 | @Valid AccountUpdateRepresentation account, 61 | @Context UriInfo uriInfo, @Context Request request) { 62 | return Response.ok().build(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/alternate/APIDefinition.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.alternate; 2 | 3 | 4 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 5 | import io.swagger.v3.oas.annotations.info.Info; 6 | 7 | @OpenAPIDefinition(info = @Info(title = "My Title", version = "1.0.0")) 8 | public interface APIDefinition { 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/alternate/AlternateResource.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.alternate; 2 | 3 | import javax.ws.rs.GET; 4 | import javax.ws.rs.Path; 5 | import javax.ws.rs.core.Response; 6 | 7 | @Path("alternate") 8 | public class AlternateResource { 9 | 10 | @GET 11 | public Response list() { 12 | return null; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/alternate/ManipulatorListener.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.alternate; 2 | 3 | import io.swagger.v3.jaxrs2.ReaderListener; 4 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 5 | import io.swagger.v3.oas.integration.api.OpenApiReader; 6 | import io.swagger.v3.oas.models.OpenAPI; 7 | import io.swagger.v3.oas.models.info.Info; 8 | 9 | @OpenAPIDefinition 10 | public class ManipulatorListener implements ReaderListener { 11 | @Override 12 | public void beforeScan(OpenApiReader reader, OpenAPI swagger) { 13 | Info info = new Info(); 14 | info.setTitle("Manipulator Title"); 15 | swagger.setInfo(info); 16 | } 17 | 18 | @Override 19 | public void afterScan(OpenApiReader reader, OpenAPI swagger) { 20 | swagger.getInfo().setDescription("Description from ReaderListener"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/app/RestApplication.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.app; 2 | 3 | import javax.ws.rs.ApplicationPath; 4 | 5 | @ApplicationPath("/api") 6 | public class RestApplication extends javax.ws.rs.core.Application { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/model/AccountRepresentation.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.model; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | 6 | import io.openapitools.jackson.dataformat.hal.HALLink; 7 | import io.openapitools.jackson.dataformat.hal.annotation.EmbeddedResource; 8 | import io.openapitools.jackson.dataformat.hal.annotation.Link; 9 | import io.openapitools.jackson.dataformat.hal.annotation.Resource; 10 | 11 | /** 12 | * Represents a single as returned from REST service. 13 | */ 14 | @Resource 15 | public class AccountRepresentation { 16 | private String regNo; 17 | private String accountNo; 18 | private String name; 19 | 20 | @EmbeddedResource("transactions") 21 | private Collection transactions; 22 | 23 | @Link("account:transactions") 24 | private HALLink transactionsResource; 25 | 26 | @Link 27 | private HALLink self; 28 | 29 | public String getRegNo() { 30 | return regNo; 31 | } 32 | 33 | public String getAccountNo() { 34 | return accountNo; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public Collection getTransactions() { 42 | if (transactions == null) { 43 | return null; 44 | } else { 45 | return Collections.unmodifiableCollection(transactions); 46 | } 47 | } 48 | 49 | public HALLink getTransactionsResource() { 50 | return transactionsResource; 51 | } 52 | 53 | public HALLink getSelf() { 54 | return self; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/model/AccountUpdateRepresentation.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.model; 2 | 3 | import javax.validation.constraints.NotNull; 4 | import javax.validation.constraints.Pattern; 5 | 6 | /** 7 | * Creation and update of account. 8 | */ 9 | public class AccountUpdateRepresentation { 10 | 11 | @Pattern(regexp = "^[0-9]{4}$") 12 | private String regNo; 13 | 14 | @Pattern(regexp = "^[0-9]+$") 15 | private String accountNo; 16 | 17 | @NotNull 18 | @Pattern(regexp = ".{1,40}") 19 | private String name; 20 | 21 | public String getRegNo() { 22 | return regNo; 23 | } 24 | 25 | public String getAccountNo() { 26 | return accountNo; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/model/AccountsRepresentation.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.model; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | 6 | import io.openapitools.jackson.dataformat.hal.HALLink; 7 | import io.openapitools.jackson.dataformat.hal.annotation.EmbeddedResource; 8 | import io.openapitools.jackson.dataformat.hal.annotation.Link; 9 | import io.openapitools.jackson.dataformat.hal.annotation.Resource; 10 | 11 | /** 12 | * Represents a set of accounts from the REST service exposure. 13 | */ 14 | @Resource 15 | public class AccountsRepresentation { 16 | 17 | @Link 18 | private HALLink self; 19 | 20 | @EmbeddedResource("accounts") 21 | private Collection accounts; 22 | 23 | public AccountsRepresentation() { 24 | } 25 | 26 | public HALLink getSelf() { 27 | return self; 28 | } 29 | 30 | public Collection getAccounts() { 31 | return Collections.unmodifiableCollection(accounts); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/model/TransactionRepresentation.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.model; 2 | 3 | import io.openapitools.jackson.dataformat.hal.HALLink; 4 | import io.openapitools.jackson.dataformat.hal.annotation.Link; 5 | import io.openapitools.jackson.dataformat.hal.annotation.Resource; 6 | 7 | /** 8 | * Represents a single transaction as returned by the REST service. 9 | */ 10 | @Resource 11 | public class TransactionRepresentation { 12 | private String id; 13 | private String description; 14 | private String amount; 15 | 16 | @Link 17 | private HALLink self; 18 | 19 | public String getId() { 20 | return id; 21 | } 22 | 23 | public String getDescription() { 24 | return description; 25 | } 26 | 27 | public String getAmount() { 28 | return amount; 29 | } 30 | 31 | public HALLink getSelf() { 32 | return self; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/io/openapitools/swagger/example/model/TransactionsRepresentation.java: -------------------------------------------------------------------------------- 1 | package io.openapitools.swagger.example.model; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | 6 | import io.openapitools.jackson.dataformat.hal.HALLink; 7 | import io.openapitools.jackson.dataformat.hal.annotation.EmbeddedResource; 8 | import io.openapitools.jackson.dataformat.hal.annotation.Link; 9 | import io.openapitools.jackson.dataformat.hal.annotation.Resource; 10 | 11 | /** 12 | * Represents a set of transactions as returned by the REST service. 13 | */ 14 | @Resource 15 | public class TransactionsRepresentation { 16 | @EmbeddedResource("transactions") 17 | private Collection transactions; 18 | 19 | @Link 20 | private HALLink self; 21 | 22 | public Collection getTransactions() { 23 | return Collections.unmodifiableCollection(transactions); 24 | } 25 | 26 | public HALLink getSelf() { 27 | return self; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/descriptions.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | This is some description to be included. -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/api/swagger.json: -------------------------------------------------------------------------------- 1 | {"openapi":"3.0.1","paths":{"/accounts":{"get":{"operationId":"list","responses":{"default":{"description":"default response","content":{"application/hal+json":{}}}}}},"/accounts/{regNo}-{accountNo}":{"get":{"description":"Get single account","operationId":"get","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"responses":{"404":{"description":"No account found."}}},"put":{"description":"Create new or update existing account","operationId":"createOrUpdate","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateRepresentation"}}}},"responses":{"404":{"description":"No updating possible"}}}}},"components":{"schemas":{"AccountUpdateRepresentation":{"required":["name"],"type":"object","properties":{"accountNo":{"pattern":"^[0-9]+$","type":"string"},"name":{"pattern":".{1,40}","type":"string"},"regNo":{"pattern":"^[0-9]{4}$","type":"string"}}}}}} -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/api/swagger.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | paths: 3 | /accounts: 4 | get: 5 | operationId: list 6 | responses: 7 | default: 8 | description: default response 9 | content: 10 | application/hal+json: {} 11 | /accounts/{regNo}-{accountNo}: 12 | get: 13 | description: Get single account 14 | operationId: get 15 | parameters: 16 | - name: regNo 17 | in: path 18 | required: true 19 | schema: 20 | pattern: "^[0-9]{4}$" 21 | type: string 22 | - name: accountNo 23 | in: path 24 | required: true 25 | schema: 26 | pattern: "^[0-9]+$" 27 | type: string 28 | responses: 29 | "404": 30 | description: No account found. 31 | put: 32 | description: Create new or update existing account 33 | operationId: createOrUpdate 34 | parameters: 35 | - name: regNo 36 | in: path 37 | required: true 38 | schema: 39 | pattern: "^[0-9]{4}$" 40 | type: string 41 | - name: accountNo 42 | in: path 43 | required: true 44 | schema: 45 | pattern: "^[0-9]+$" 46 | type: string 47 | requestBody: 48 | content: 49 | application/json: 50 | schema: 51 | $ref: '#/components/schemas/AccountUpdateRepresentation' 52 | responses: 53 | "404": 54 | description: No updating possible 55 | components: 56 | schemas: 57 | AccountUpdateRepresentation: 58 | required: 59 | - name 60 | type: object 61 | properties: 62 | accountNo: 63 | pattern: "^[0-9]+$" 64 | type: string 65 | name: 66 | pattern: ".{1,40}" 67 | type: string 68 | regNo: 69 | pattern: "^[0-9]{4}$" 70 | type: string 71 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/application/swagger.json: -------------------------------------------------------------------------------- 1 | {"openapi":"3.0.1","info":{"title":"My Title","description":"Description from ReaderListener","version":"1.0.0"},"paths":{"/api/accounts":{"get":{"operationId":"list","responses":{"default":{"description":"default response","content":{"application/hal+json":{}}}}}},"/api/accounts/{regNo}-{accountNo}":{"get":{"description":"Get single account","operationId":"get","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"responses":{"404":{"description":"No account found."}}},"put":{"description":"Create new or update existing account","operationId":"createOrUpdate","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateRepresentation"}}}},"responses":{"404":{"description":"No updating possible"}}}},"/api/alternate":{"get":{"operationId":"list_1","responses":{"default":{"description":"default response","content":{"*/*":{}}}}}}},"components":{"schemas":{"AccountUpdateRepresentation":{"required":["name"],"type":"object","properties":{"accountNo":{"pattern":"^[0-9]+$","type":"string"},"name":{"pattern":".{1,40}","type":"string"},"regNo":{"pattern":"^[0-9]{4}$","type":"string"}}}}}} -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/application_scan/swagger.json: -------------------------------------------------------------------------------- 1 | {"openapi":"3.0.1","info":{"title":"My Title","description":"Description from ReaderListener","version":"1.0.0"},"paths":{"/api/accounts":{"get":{"operationId":"list","responses":{"default":{"description":"default response","content":{"application/hal+json":{}}}}}},"/api/accounts/{regNo}-{accountNo}":{"get":{"description":"Get single account","operationId":"get","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"404":{"description":"No account found."}}},"put":{"description":"Create new or update existing account","operationId":"createOrUpdate","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateRepresentation"}}}},"responses":{"404":{"description":"No updating possible"}}}},"/api/alternate":{"get":{"operationId":"list_1","responses":{"default":{"description":"default response","content":{"*/*":{}}}}}}},"components":{"schemas":{"AccountUpdateRepresentation":{"required":["name"],"type":"object","properties":{"regNo":{"pattern":"^[0-9]{4}$","type":"string"},"accountNo":{"pattern":"^[0-9]+$","type":"string"},"name":{"pattern":".{1,40}","type":"string"}}}}}} 2 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/default/swagger.json: -------------------------------------------------------------------------------- 1 | {"openapi":"3.0.1","info":{"title":"My Title","description":"Description from ReaderListener","version":"1.0.0"},"paths":{"/accounts":{"get":{"operationId":"list","responses":{"default":{"description":"default response","content":{"application/hal+json":{}}}}}},"/accounts/{regNo}-{accountNo}":{"get":{"description":"Get single account","operationId":"get","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"responses":{"404":{"description":"No account found."}}},"put":{"description":"Create new or update existing account","operationId":"createOrUpdate","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateRepresentation"}}}},"responses":{"404":{"description":"No updating possible"}}}},"/alternate":{"get":{"operationId":"list_1","responses":{"default":{"description":"default response","content":{"*/*":{}}}}}}},"components":{"schemas":{"AccountUpdateRepresentation":{"required":["name"],"type":"object","properties":{"accountNo":{"pattern":"^[0-9]+$","type":"string"},"name":{"pattern":".{1,40}","type":"string"},"regNo":{"pattern":"^[0-9]{4}$","type":"string"}}}}}} -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/full/open-api.json: -------------------------------------------------------------------------------- 1 | {"openapi":"3.0.1","info":{"title":"Title","description":"# Description\n\nThis is some description to be included.","termsOfService":"Terms","contact":{"name":"My Name","url":"https://google.com","email":"e@mail.com"},"license":{"name":"MIT","url":"https://license"},"version":"1.0.0","x-custom-property":"In Info"},"externalDocs":{"description":"Some external doc at config level","url":"https://example.org","x-custom-property":"In configs's external document"},"servers":[{"url":"https://{sub}.example.it/base/path","description":"Example URL","variables":{"sub":{"description":"The Subdomain","default":"services","enum":["services","web","main"],"x-custom-property":"In ServerVariable"}},"x-custom-property":"In Server"}],"security":[{"first":[]},{"third":["requiredScope1","requiredScope2"]}],"tags":[{"name":"MyTag","description":"MyDescription","externalDocs":{"description":"Some tag's external doc","url":"https://tag.example.org","x-custom-property":"In tag's external document"},"x-custom-property":"In tag"}],"paths":{"/accounts":{"get":{"operationId":"list","responses":{"default":{"description":"default response","content":{"application/hal+json":{}}}}}},"/accounts/{regNo}-{accountNo}":{"get":{"description":"Get single account","operationId":"get","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"responses":{"404":{"description":"No account found."}}},"put":{"description":"Create new or update existing account","operationId":"createOrUpdate","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateRepresentation"}}}},"responses":{"404":{"description":"No updating possible"}}}}},"components":{"schemas":{"AccountUpdateRepresentation":{"required":["name"],"type":"object","properties":{"accountNo":{"pattern":"^[0-9]+$","type":"string"},"name":{"pattern":".{1,40}","type":"string"},"regNo":{"pattern":"^[0-9]{4}$","type":"string"}}}},"securitySchemes":{"first":{"type":"apiKey","description":"Via web gateway","name":"X-API-TOKEN","in":"header"},"fourth":{"type":"openIdConnect","openIdConnectUrl":"https://id.example.org"},"second":{"type":"http","scheme":"MyCredentials","bearerFormat":"password"},"third":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.example.org","refreshUrl":"https://refresh.example.org","scopes":{"x":"y"},"x-custom-property":"In third SecurityScheme's implicit flow"},"password":{"tokenUrl":"https://token.example.org"},"clientCredentials":{"tokenUrl":"https://client.token.example.org"},"authorizationCode":{"authorizationUrl":"https://code.auth.example.org","tokenUrl":"https://code.token.example.org"},"x-custom-property":"In third SecurityScheme's flow"}}}},"x-custom-property":"In Config"} -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/full/open-api.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | info: 3 | title: Title 4 | description: |- 5 | # Description 6 | 7 | This is some description to be included. 8 | termsOfService: Terms 9 | contact: 10 | name: My Name 11 | url: https://google.com 12 | email: e@mail.com 13 | license: 14 | name: MIT 15 | url: https://license 16 | version: 1.0.0 17 | x-custom-property: In Info 18 | externalDocs: 19 | description: Some external doc at config level 20 | url: https://example.org 21 | x-custom-property: In configs's external document 22 | servers: 23 | - url: "https://{sub}.example.it/base/path" 24 | description: Example URL 25 | variables: 26 | sub: 27 | description: The Subdomain 28 | default: services 29 | enum: 30 | - services 31 | - web 32 | - main 33 | x-custom-property: In ServerVariable 34 | x-custom-property: In Server 35 | security: 36 | - first: [] 37 | - third: 38 | - requiredScope1 39 | - requiredScope2 40 | tags: 41 | - name: MyTag 42 | description: MyDescription 43 | externalDocs: 44 | description: Some tag's external doc 45 | url: https://tag.example.org 46 | x-custom-property: In tag's external document 47 | x-custom-property: In tag 48 | paths: 49 | /accounts: 50 | get: 51 | operationId: list 52 | responses: 53 | default: 54 | description: default response 55 | content: 56 | application/hal+json: {} 57 | /accounts/{regNo}-{accountNo}: 58 | get: 59 | description: Get single account 60 | operationId: get 61 | parameters: 62 | - name: regNo 63 | in: path 64 | required: true 65 | schema: 66 | pattern: "^[0-9]{4}$" 67 | type: string 68 | - name: accountNo 69 | in: path 70 | required: true 71 | schema: 72 | pattern: "^[0-9]+$" 73 | type: string 74 | responses: 75 | "404": 76 | description: No account found. 77 | put: 78 | description: Create new or update existing account 79 | operationId: createOrUpdate 80 | parameters: 81 | - name: regNo 82 | in: path 83 | required: true 84 | schema: 85 | pattern: "^[0-9]{4}$" 86 | type: string 87 | - name: accountNo 88 | in: path 89 | required: true 90 | schema: 91 | pattern: "^[0-9]+$" 92 | type: string 93 | requestBody: 94 | content: 95 | application/json: 96 | schema: 97 | $ref: '#/components/schemas/AccountUpdateRepresentation' 98 | responses: 99 | "404": 100 | description: No updating possible 101 | components: 102 | schemas: 103 | AccountUpdateRepresentation: 104 | required: 105 | - name 106 | type: object 107 | properties: 108 | accountNo: 109 | pattern: "^[0-9]+$" 110 | type: string 111 | name: 112 | pattern: ".{1,40}" 113 | type: string 114 | regNo: 115 | pattern: "^[0-9]{4}$" 116 | type: string 117 | securitySchemes: 118 | first: 119 | type: apiKey 120 | description: Via web gateway 121 | name: X-API-TOKEN 122 | in: header 123 | fourth: 124 | type: openIdConnect 125 | openIdConnectUrl: https://id.example.org 126 | second: 127 | type: http 128 | scheme: MyCredentials 129 | bearerFormat: password 130 | third: 131 | type: oauth2 132 | flows: 133 | implicit: 134 | authorizationUrl: https://auth.example.org 135 | refreshUrl: https://refresh.example.org 136 | scopes: 137 | x: "y" 138 | x-custom-property: In third SecurityScheme's implicit flow 139 | password: 140 | tokenUrl: https://token.example.org 141 | clientCredentials: 142 | tokenUrl: https://client.token.example.org 143 | authorizationCode: 144 | authorizationUrl: https://code.auth.example.org 145 | tokenUrl: https://code.token.example.org 146 | x-custom-property: In third SecurityScheme's flow 147 | x-custom-property: In Config 148 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/fullpretty/open-api.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi" : "3.0.1", 3 | "info" : { 4 | "title" : "Title", 5 | "description" : "# Description\n\nThis is some description to be included.", 6 | "termsOfService" : "Terms", 7 | "contact" : { 8 | "name" : "My Name", 9 | "url" : "https://google.com", 10 | "email" : "e@mail.com" 11 | }, 12 | "license" : { 13 | "name" : "MIT", 14 | "url" : "https://license" 15 | }, 16 | "version" : "1.0.0", 17 | "x-custom-property" : "My custom property" 18 | }, 19 | "servers" : [ { 20 | "url" : "https://services.example.it/base/path", 21 | "description" : "Example URL" 22 | } ], 23 | "paths" : { 24 | "/accounts" : { 25 | "get" : { 26 | "operationId" : "list", 27 | "responses" : { 28 | "default" : { 29 | "description" : "default response", 30 | "content" : { 31 | "application/hal+json" : { } 32 | } 33 | } 34 | } 35 | } 36 | }, 37 | "/accounts/{regNo}-{accountNo}" : { 38 | "get" : { 39 | "description" : "Get single account", 40 | "operationId" : "get", 41 | "parameters" : [ { 42 | "name" : "regNo", 43 | "in" : "path", 44 | "required" : true, 45 | "schema" : { 46 | "pattern" : "^[0-9]{4}$", 47 | "type" : "string" 48 | } 49 | }, { 50 | "name" : "accountNo", 51 | "in" : "path", 52 | "required" : true, 53 | "schema" : { 54 | "pattern" : "^[0-9]+$", 55 | "type" : "string" 56 | } 57 | } ], 58 | "responses" : { 59 | "404" : { 60 | "description" : "No account found." 61 | } 62 | } 63 | }, 64 | "put" : { 65 | "description" : "Create new or update existing account", 66 | "operationId" : "createOrUpdate", 67 | "parameters" : [ { 68 | "name" : "regNo", 69 | "in" : "path", 70 | "required" : true, 71 | "schema" : { 72 | "pattern" : "^[0-9]{4}$", 73 | "type" : "string" 74 | } 75 | }, { 76 | "name" : "accountNo", 77 | "in" : "path", 78 | "required" : true, 79 | "schema" : { 80 | "pattern" : "^[0-9]+$", 81 | "type" : "string" 82 | } 83 | } ], 84 | "requestBody" : { 85 | "content" : { 86 | "application/json" : { 87 | "schema" : { 88 | "$ref" : "#/components/schemas/AccountUpdateRepresentation" 89 | } 90 | } 91 | } 92 | }, 93 | "responses" : { 94 | "404" : { 95 | "description" : "No updating possible" 96 | } 97 | } 98 | } 99 | } 100 | }, 101 | "components" : { 102 | "schemas" : { 103 | "AccountUpdateRepresentation" : { 104 | "required" : [ "name" ], 105 | "type" : "object", 106 | "properties" : { 107 | "accountNo" : { 108 | "pattern" : "^[0-9]+$", 109 | "type" : "string" 110 | }, 111 | "name" : { 112 | "pattern" : ".{1,40}", 113 | "type" : "string" 114 | }, 115 | "regNo" : { 116 | "pattern" : "^[0-9]{4}$", 117 | "type" : "string" 118 | } 119 | } 120 | } 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/fullpretty/open-api.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | info: 3 | title: Title 4 | description: |- 5 | # Description 6 | 7 | This is some description to be included. 8 | termsOfService: Terms 9 | contact: 10 | name: My Name 11 | url: https://google.com 12 | email: e@mail.com 13 | license: 14 | name: MIT 15 | url: https://license 16 | version: 1.0.0 17 | x-custom-property: My custom property 18 | servers: 19 | - url: https://services.example.it/base/path 20 | description: Example URL 21 | paths: 22 | /accounts: 23 | get: 24 | operationId: list 25 | responses: 26 | default: 27 | description: default response 28 | content: 29 | application/hal+json: {} 30 | /accounts/{regNo}-{accountNo}: 31 | get: 32 | description: Get single account 33 | operationId: get 34 | parameters: 35 | - name: regNo 36 | in: path 37 | required: true 38 | schema: 39 | pattern: "^[0-9]{4}$" 40 | type: string 41 | - name: accountNo 42 | in: path 43 | required: true 44 | schema: 45 | pattern: "^[0-9]+$" 46 | type: string 47 | responses: 48 | "404": 49 | description: No account found. 50 | put: 51 | description: Create new or update existing account 52 | operationId: createOrUpdate 53 | parameters: 54 | - name: regNo 55 | in: path 56 | required: true 57 | schema: 58 | pattern: "^[0-9]{4}$" 59 | type: string 60 | - name: accountNo 61 | in: path 62 | required: true 63 | schema: 64 | pattern: "^[0-9]+$" 65 | type: string 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: '#/components/schemas/AccountUpdateRepresentation' 71 | responses: 72 | "404": 73 | description: No updating possible 74 | components: 75 | schemas: 76 | AccountUpdateRepresentation: 77 | required: 78 | - name 79 | type: object 80 | properties: 81 | accountNo: 82 | pattern: "^[0-9]+$" 83 | type: string 84 | name: 85 | pattern: ".{1,40}" 86 | type: string 87 | regNo: 88 | pattern: "^[0-9]{4}$" 89 | type: string 90 | -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/recursive/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi" : "3.0.1", 3 | "info" : { 4 | "title" : "My Title", 5 | "description" : "Description from ReaderListener", 6 | "version" : "1.0.0" 7 | }, 8 | "paths" : { 9 | "/api/accounts" : { 10 | "get" : { 11 | "operationId" : "list", 12 | "responses" : { 13 | "default" : { 14 | "description" : "default response", 15 | "content" : { 16 | "application/hal+json" : { } 17 | } 18 | } 19 | } 20 | } 21 | }, 22 | "/api/accounts/{regNo}-{accountNo}" : { 23 | "get" : { 24 | "description" : "Get single account", 25 | "operationId" : "get", 26 | "parameters" : [ { 27 | "name" : "regNo", 28 | "in" : "path", 29 | "required" : true, 30 | "schema" : { 31 | "pattern" : "^[0-9]{4}$", 32 | "type" : "string" 33 | } 34 | }, { 35 | "name" : "accountNo", 36 | "in" : "path", 37 | "required" : true, 38 | "schema" : { 39 | "pattern" : "^[0-9]+$", 40 | "type" : "string" 41 | } 42 | } ], 43 | "responses" : { 44 | "404" : { 45 | "description" : "No account found." 46 | } 47 | } 48 | }, 49 | "put" : { 50 | "description" : "Create new or update existing account", 51 | "operationId" : "createOrUpdate", 52 | "parameters" : [ { 53 | "name" : "regNo", 54 | "in" : "path", 55 | "required" : true, 56 | "schema" : { 57 | "pattern" : "^[0-9]{4}$", 58 | "type" : "string" 59 | } 60 | }, { 61 | "name" : "accountNo", 62 | "in" : "path", 63 | "required" : true, 64 | "schema" : { 65 | "pattern" : "^[0-9]+$", 66 | "type" : "string" 67 | } 68 | } ], 69 | "requestBody" : { 70 | "content" : { 71 | "application/json" : { 72 | "schema" : { 73 | "$ref" : "#/components/schemas/AccountUpdateRepresentation" 74 | } 75 | } 76 | } 77 | }, 78 | "responses" : { 79 | "404" : { 80 | "description" : "No updating possible" 81 | } 82 | } 83 | } 84 | }, 85 | "/api/alternate" : { 86 | "get" : { 87 | "operationId" : "list_1", 88 | "responses" : { 89 | "default" : { 90 | "description" : "default response", 91 | "content" : { 92 | "*/*" : { } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | }, 99 | "components" : { 100 | "schemas" : { 101 | "AccountUpdateRepresentation" : { 102 | "required" : [ "name" ], 103 | "type" : "object", 104 | "properties" : { 105 | "accountNo" : { 106 | "pattern" : "^[0-9]+$", 107 | "type" : "string" 108 | }, 109 | "name" : { 110 | "pattern" : ".{1,40}", 111 | "type" : "string" 112 | }, 113 | "regNo" : { 114 | "pattern" : "^[0-9]{4}$", 115 | "type" : "string" 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/semifull/swagger.json: -------------------------------------------------------------------------------- 1 | {"openapi":"3.0.1","info":{"title":"Title","description":"# Description\n\nThis is some description to be included.","termsOfService":"Terms","contact":{"name":"My Name","url":"https://google.com","email":"e@mail.com"},"license":{"name":"MIT","url":"https://license"},"version":"1.0.0"},"servers":[{"url":"https://services.example.it/base/path","description":"Example URL"}],"paths":{"/accounts":{"get":{"operationId":"list","responses":{"default":{"description":"default response","content":{"application/hal+json":{}}}}}},"/accounts/{regNo}-{accountNo}":{"get":{"description":"Get single account","operationId":"get","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"responses":{"404":{"description":"No account found."}}},"put":{"description":"Create new or update existing account","operationId":"createOrUpdate","parameters":[{"name":"regNo","in":"path","required":true,"schema":{"pattern":"^[0-9]{4}$","type":"string"}},{"name":"accountNo","in":"path","required":true,"schema":{"pattern":"^[0-9]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUpdateRepresentation"}}}},"responses":{"404":{"description":"No updating possible"}}}}},"components":{"schemas":{"AccountUpdateRepresentation":{"required":["name"],"type":"object","properties":{"accountNo":{"pattern":"^[0-9]+$","type":"string"},"name":{"pattern":".{1,40}","type":"string"},"regNo":{"pattern":"^[0-9]{4}$","type":"string"}}}}}} -------------------------------------------------------------------------------- /src/test/resources/expectedOutput/semifull/swagger.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | info: 3 | title: Title 4 | description: |- 5 | # Description 6 | 7 | This is some description to be included. 8 | termsOfService: Terms 9 | contact: 10 | name: My Name 11 | url: https://google.com 12 | email: e@mail.com 13 | license: 14 | name: MIT 15 | url: https://license 16 | version: 1.0.0 17 | servers: 18 | - url: https://services.example.it/base/path 19 | description: Example URL 20 | paths: 21 | /accounts: 22 | get: 23 | operationId: list 24 | responses: 25 | default: 26 | description: default response 27 | content: 28 | application/hal+json: {} 29 | /accounts/{regNo}-{accountNo}: 30 | get: 31 | description: Get single account 32 | operationId: get 33 | parameters: 34 | - name: regNo 35 | in: path 36 | required: true 37 | schema: 38 | pattern: "^[0-9]{4}$" 39 | type: string 40 | - name: accountNo 41 | in: path 42 | required: true 43 | schema: 44 | pattern: "^[0-9]+$" 45 | type: string 46 | responses: 47 | "404": 48 | description: No account found. 49 | put: 50 | description: Create new or update existing account 51 | operationId: createOrUpdate 52 | parameters: 53 | - name: regNo 54 | in: path 55 | required: true 56 | schema: 57 | pattern: "^[0-9]{4}$" 58 | type: string 59 | - name: accountNo 60 | in: path 61 | required: true 62 | schema: 63 | pattern: "^[0-9]+$" 64 | type: string 65 | requestBody: 66 | content: 67 | application/json: 68 | schema: 69 | $ref: '#/components/schemas/AccountUpdateRepresentation' 70 | responses: 71 | "404": 72 | description: No updating possible 73 | components: 74 | schemas: 75 | AccountUpdateRepresentation: 76 | required: 77 | - name 78 | type: object 79 | properties: 80 | accountNo: 81 | pattern: "^[0-9]+$" 82 | type: string 83 | name: 84 | pattern: ".{1,40}" 85 | type: string 86 | regNo: 87 | pattern: "^[0-9]{4}$" 88 | type: string 89 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-application-scan.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | io.openapitools.swagger.example 20 | io.openapitools.swagger.example.alternate 21 | io.openapitools.swagger.example.app 22 | 23 | target/application 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-application.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | io.openapitools.swagger.example 20 | io.openapitools.swagger.example.alternate 21 | 22 | target/application 23 | io.openapitools.swagger.example.app.RestApplication 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-defaults-pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | io.openapitools.swagger.example 20 | io.openapitools.swagger.example.alternate 21 | 22 | target/default 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-full-nofilename-pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | 20 | 21 | https://services.example.it/base/path 22 | Example URL 23 | 24 | 25 | 26 | Title 27 | 1.0.0 28 | Terms 29 | 30 | e@mail.com 31 | My Name 32 | https://google.com 33 | 34 | 35 | https://license 36 | MIT 37 | 38 | 39 | src/test/resources/descriptions.md 40 | 41 | 42 | io.openapitools.swagger.example 43 | 44 | 45 | JSON 46 | YAML 47 | 48 | target/semifull 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-full-pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | 20 | Title 21 | 1.0.0 22 | Terms 23 | 24 | e@mail.com 25 | My Name 26 | https://google.com 27 | 28 | 29 | https://license 30 | MIT 31 | 32 | 33 | In Info 34 | 35 | 36 | src/test/resources/descriptions.md 37 | 38 | 39 | https://{sub}.example.it/base/path 40 | Example URL 41 | 42 | 43 | The Subdomain 44 | services 45 | 46 | services 47 | web 48 | main 49 | 50 | 51 | In ServerVariable 52 | 53 | 54 | 55 | 56 | In Server 57 | 58 | 59 | 60 | 61 | 62 | 63 | apikey 64 | Via web gateway 65 | X-API-TOKEN 66 | header 67 | 68 | In first SecurityScheme 69 | 70 | 71 | 72 | http 73 | MyCredentials 74 | password 75 | 76 | 77 | oauth2 78 | 79 | 80 | https://auth.example.org 81 | https://refresh.example.org 82 | 83 | y 84 | 85 | 86 | In third SecurityScheme's implicit flow 87 | 88 | 89 | 90 | https://token.example.org 91 | 92 | 93 | 94 | https://client.token.example.org 95 | 96 | 97 | 98 | https://code.auth.example.org 99 | https://code.token.example.org 100 | 101 | 102 | 103 | In third SecurityScheme's flow 104 | 105 | 106 | 107 | 108 | openIdConnect 109 | https://id.example.org 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | first 118 | 119 | 120 | 121 | 122 | 123 | 124 | third 125 | 126 | requiredScope1 127 | requiredScope2 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | MyTag 136 | MyDescription 137 | 138 | Some tag's external doc 139 | https://tag.example.org 140 | 141 | In tag's external document 142 | 143 | 144 | 145 | In tag 146 | 147 | 148 | 149 | 150 | Some external doc at config level 151 | https://example.org 152 | 153 | In configs's external document 154 | 155 | 156 | 157 | In Config 158 | 159 | 160 | 161 | io.openapitools.swagger.example 162 | 163 | 164 | JSON 165 | YAML 166 | 167 | target/full 168 | open-api 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-full-pretty-pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | 20 | 21 | https://services.example.it/base/path 22 | Example URL 23 | 24 | 25 | 26 | Title 27 | 1.0.0 28 | Terms 29 | 30 | e@mail.com 31 | My Name 32 | https://google.com 33 | 34 | 35 | https://license 36 | MIT 37 | 38 | 39 | My custom property 40 | 41 | 42 | src/test/resources/descriptions.md 43 | 44 | 45 | io.openapitools.swagger.example 46 | 47 | 48 | JSON 49 | YAML 50 | 51 | target/fullpretty 52 | open-api 53 | true 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | io.openapitools.swagger.example 20 | 21 | 22 | JSON 23 | YAML 24 | 25 | target/api 26 | swagger 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/test/resources/generate-mojo-recursive-pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.openapitools.swagger.test 5 | mojo-test 6 | jar 7 | 1.0.0-SNAPSHOT 8 | Swagger Generate Maven Mojo 9 | 10 | 11 | 12 | 13 | 14 | 15 | io.openapitools.swagger 16 | swagger-maven-plugin 17 | 18 | 19 | io.openapitools.swagger.example 20 | 21 | target/recursive 22 | true 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | --------------------------------------------------------------------------------