[maven-plugin] Generate hash from actual resolved spec rather than inputSpec file (#18849)

* Ensure temp directories are deleted after test execution

* Implement test that external $ref changes are reflected in checksum

* Generate hash checksum from actual resolved spec instead of inputSpec file

Otherwise regeneration will not happen when skipIfSpecIsUnchanged is enabled,
although formally the spec content has changed.

Fixes #4512 and #16489

* Use try-with-resources to ensure stream is closed properly on exit

* Fix deprecation warning on SimpleLocalRepositoryManagerFactory no-arg constructor

* Apply minor code cleanup

- use fluent setters where possible
- remove undocumented @throws from JavaDoc
- use List.of() instead of Arrays.asList() for single-element-collection
  (more memory efficient)
- fix some grammar issues in comments and JavaDoc

* Use non-blocking java.nio API for file existence checks
This commit is contained in:
Philzen 2024-06-05 11:19:22 +02:00 committed by GitHub
parent 446e168f43
commit 880df7a7a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 337 additions and 176 deletions

View File

@ -17,40 +17,14 @@
package org.openapitools.codegen.plugin;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.*;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.core.util.Yaml;
import io.swagger.v3.parser.OpenAPIResolver;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.AuthorizationValue;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import com.google.common.io.ByteSource;
import com.google.common.io.CharSource;
import io.swagger.v3.parser.core.models.ParseOptions;
import io.swagger.v3.parser.util.ClasspathHelper;
import lombok.Setter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
@ -59,30 +33,28 @@ import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.plugins.annotations.*;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.auth.AuthParser;
import org.openapitools.codegen.*;
import org.openapitools.codegen.config.CodegenConfigurator;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.config.MergedSpecBuilder;
import org.sonatype.plexus.build.incremental.BuildContext;
import org.sonatype.plexus.build.incremental.DefaultBuildContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.plexus.build.incremental.BuildContext;
import org.sonatype.plexus.build.incremental.DefaultBuildContext;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.*;
/**
* Goal which generates client/server code from a OpenAPI json/yaml definition.
@ -609,19 +581,11 @@ public class CodeGenMojo extends AbstractMojo {
}
if (Boolean.TRUE.equals(skipIfSpecIsUnchanged)) {
File storedInputSpecHashFile = getHashFile(inputSpecFile);
final File storedInputSpecHashFile = getHashFile(inputSpecFile);
if (storedInputSpecHashFile.exists()) {
String inputSpecHash = null;
try {
inputSpecHash = calculateInputSpecHash(inputSpecFile);
} catch (IOException ex) {
ex.printStackTrace();
}
@SuppressWarnings("UnstableApiUsage")
String storedInputSpecHash = Files.asCharSource(storedInputSpecHashFile, StandardCharsets.UTF_8).read();
if (storedInputSpecHash.equals(inputSpecHash)) {
getLog().info(
"Code generation is skipped because input was unchanged");
if (storedInputSpecHash.equals(calculateInputSpecHash(inputSpec))) {
getLog().info("Code generation is skipped because input was unchanged");
return;
}
}
@ -1010,8 +974,6 @@ public class CodeGenMojo extends AbstractMojo {
// Store a checksum of the input spec
File storedInputSpecHashFile = getHashFile(inputSpecFile);
String inputSpecHash = calculateInputSpecHash(inputSpecFile);
if (storedInputSpecHashFile.getParent() != null && !new File(storedInputSpecHashFile.getParent()).exists()) {
File parent = new File(storedInputSpecHashFile.getParent());
if (!parent.mkdirs()) {
@ -1019,8 +981,8 @@ public class CodeGenMojo extends AbstractMojo {
" to store the checksum of the input spec.");
}
}
Files.asCharSink(storedInputSpecHashFile, StandardCharsets.UTF_8).write(inputSpecHash);
Files.asCharSink(storedInputSpecHashFile, StandardCharsets.UTF_8).write(calculateInputSpecHash(inputSpec));
} catch (Exception e) {
// Maven logs exceptions thrown by plugins only if invoked with -e
// I find it annoying to jump through hoops to get basic diagnostic information,
@ -1035,45 +997,21 @@ public class CodeGenMojo extends AbstractMojo {
}
/**
* Calculate openapi specification file hash. If specification is hosted on remote resource it is downloaded first
* Calculate an SHA256 hash for the openapi specification.
* If the specification is hosted on a remote resource it is downloaded first.
*
* @param inputSpecFile - Openapi specification input file to calculate its hash.
* Does not take into account if input spec is hosted on remote resource
* @return openapi specification file hash
* @throws IOException
* @param inputSpec - Openapi specification input file. Can denote a URL or file path.
* @return openapi specification hash
*/
private String calculateInputSpecHash(File inputSpecFile) throws IOException {
URL inputSpecRemoteUrl = inputSpecRemoteUrl();
File inputSpecTempFile = inputSpecFile;
if (inputSpecRemoteUrl != null) {
inputSpecTempFile = java.nio.file.Files.createTempFile("openapi-spec", ".tmp").toFile();
URLConnection conn = inputSpecRemoteUrl.openConnection();
if (isNotEmpty(auth)) {
List<AuthorizationValue> authList = AuthParser.parse(auth);
for (AuthorizationValue a : authList) {
conn.setRequestProperty(a.getKeyName(), a.getValue());
}
}
try (ReadableByteChannel readableByteChannel = Channels.newChannel(conn.getInputStream())) {
FileChannel fileChannel;
try (FileOutputStream fileOutputStream = new FileOutputStream(inputSpecTempFile)) {
fileChannel = fileOutputStream.getChannel();
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
}
}
}
ByteSource inputSpecByteSource =
inputSpecTempFile.exists()
? Files.asByteSource(inputSpecTempFile)
: CharSource.wrap(ClasspathHelper.loadFileFromClasspath(inputSpecTempFile.toString().replaceAll("\\\\","/")))
.asByteSource(StandardCharsets.UTF_8);
return inputSpecByteSource.hash(Hashing.sha256()).toString();
private String calculateInputSpecHash(String inputSpec) {
final ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true);
final URL remoteUrl = inputSpecRemoteUrl();
return Hashing.sha256().hashBytes(
new OpenAPIParser().readLocation(remoteUrl == null ? inputSpec : remoteUrl.toString(), null, parseOptions)
.getOpenAPI().toString().getBytes(StandardCharsets.UTF_8)
).toString();
}
/**

View File

@ -16,17 +16,6 @@
package org.openapitools.codegen.plugin;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
@ -39,9 +28,24 @@ import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.internal.impl.DefaultLocalPathComposer;
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
import org.eclipse.aether.repository.LocalRepository;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class CodeGenMojoTest extends BaseTestCase {
@Override
protected void setUp() throws Exception {
@ -62,8 +66,7 @@ public class CodeGenMojoTest extends BaseTestCase {
@SuppressWarnings("unchecked")
private void testCommonConfiguration(String profile) throws Exception {
File folder = Files.createTempDirectory("test").toFile();
CodeGenMojo mojo = loadMojo(folder, "src/test/resources/default", profile);
CodeGenMojo mojo = loadMojo(newTempFolder(), "src/test/resources/default", profile);
mojo.execute();
assertEquals("java", getVariableValueFromObject(mojo, "generatorName"));
assertEquals("jersey2", getVariableValueFromObject(mojo, "library"));
@ -79,43 +82,42 @@ public class CodeGenMojoTest extends BaseTestCase {
public void testHashGenerationFileContainsExecutionId() throws Exception {
// GIVEN
Path folder = Files.createTempDirectory("test");
CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/default", "file", "executionId");
final Path tempDir = newTempFolder();
CodeGenMojo mojo = loadMojo(tempDir, "src/test/resources/default", "file", "executionId");
// WHEN
mojo.execute();
// THEN
Path hashFolder = folder.resolve("target/generated-sources/common-maven/remote-openapi/.openapi-generator");
assertTrue(hashFolder.resolve("petstore.yaml-executionId.sha256").toFile().exists());
assertTrue(Files.exists(tempDir.resolve(
"target/generated-sources/common-maven/remote-openapi/.openapi-generator/petstore.yaml-executionId.sha256"
)));
}
/**
* For a Pom file which refers to a input file which will be on the classpath, as opposed to a file path,
* For a Pom file which refers to an input file which will be on the classpath, as opposed to a file path,
* test that the spec is not regenerated when the hash has not changed.
*
* @throws Exception
*/
public void testSkipRegenerationForClasspathSpecFileNoChange() throws Exception {
//GIVEN
/* Setup the mojo */
final Path folder = Files.createTempDirectory("test-classpath");
final CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/classpath", null, "executionId");
/* Set up the mojo */
final Path tempDir = newTempFolder();
final CodeGenMojo mojo = loadMojo(tempDir, "src/test/resources/classpath", null, "executionId");
/* Perform an initial generation */
mojo.execute();
/* Check the hash file was created */
final Path hashFolder = folder.resolve("target/generated-sources/common-maven/remote-openapi/.openapi-generator");
assertTrue(hashFolder.resolve("petstore-on-classpath.yaml-executionId.sha256").toFile().exists());
final Path generatedDir = tempDir.resolve("target/generated-sources/common-maven/remote-openapi");
assertTrue(Files.exists(
generatedDir.resolve(".openapi-generator/petstore-on-classpath.yaml-executionId.sha256")
));
/* Remove the generated source */
Files.walk(folder.resolve("target/generated-sources/common-maven/remote-openapi/src"))
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
try (Stream<Path> files = Files.walk(generatedDir.resolve("src"))) {
//noinspection ResultOfMethodCallIgnored
files.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
}
// WHEN
/* Execute the mojo again */
@ -123,41 +125,37 @@ public class CodeGenMojoTest extends BaseTestCase {
// THEN
/* Verify that the source directory has not been repopulated. If it has then we generated code again */
assertFalse("src directory should not have been regenerated",
folder.resolve("target/generated-sources/common-maven/remote-openapi/src").toFile().exists());
assertFalse("src directory should not have been regenerated", Files.exists(generatedDir.resolve("src")));
}
/**
* For a Pom file which refers to a input file which will be on the classpath, as opposed to a file path,
* For a Pom file which refers to an input file which will be on the classpath, as opposed to a file path,
* test that the generated source is regenerated when the hash has changed.
*
* @throws Exception
*/
public void testSkipRegenerationForClasspathSpecFileWithChange() throws Exception {
//GIVEN
/* Setup the mojo */
final Path folder = Files.createTempDirectory("test-classpath");
final CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/classpath", null, "executionId");
/* Set up the mojo */
final Path tempDir = newTempFolder();
final CodeGenMojo mojo = loadMojo(tempDir, "src/test/resources/classpath", null, "executionId");
/* Perform an initial generation */
mojo.execute();
/* Check the hash file was created, proving a generation occurred */
final Path hashFolder = folder.resolve("target/generated-sources/common-maven/remote-openapi/.openapi-generator");
assertTrue(hashFolder.resolve("petstore-on-classpath.yaml-executionId.sha256").toFile().exists());
final Path generatedDir = tempDir.resolve("target/generated-sources/common-maven/remote-openapi");
assertTrue(Files.exists(generatedDir.resolve(".openapi-generator/petstore-on-classpath.yaml-executionId.sha256")));
/* Update the hash contents to be a different value, simulating a spec change */
Files.write(
hashFolder.resolve("petstore-on-classpath.yaml-executionId.sha256"),
Arrays.asList("bd1bf4a953c858f9d47b67ed6029daacf1707e5cbd3d2e4b01383ba30363366f"));
generatedDir.resolve(".openapi-generator/petstore-on-classpath.yaml-executionId.sha256"),
List.of("bd1bf4a953c858f9d47b67ed6029daacf1707e5cbd3d2e4b01383ba30363366f")
);
/* Remove the generated source */
Files.walk(folder.resolve("target/generated-sources/common-maven/remote-openapi/src"))
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
try(Stream<Path> files = Files.walk(generatedDir.resolve("src"))) {
//noinspection ResultOfMethodCallIgnored
files.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
}
// WHEN
@ -165,29 +163,27 @@ public class CodeGenMojoTest extends BaseTestCase {
mojo.execute();
// THEN
/* Verify that the source directory has not been repopulated. If it has then we generated code again */
assertTrue("src directory should have been regenerated",
folder.resolve("target/generated-sources/common-maven/remote-openapi/src").toFile().exists());
/* Verify that the source directory has been repopulated. */
assertTrue("src directory should have been regenerated", Files.exists(generatedDir.resolve("src")));
}
public void testCollapsedSpecProduced() throws Exception {
// GIVEN
Path folder = Files.createTempDirectory("test");
CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/default", "file", "executionId");
final Path tempDir = newTempFolder();
CodeGenMojo mojo = loadMojo(tempDir, "src/test/resources/default", "file", "executionId");
// WHEN
mojo.execute();
// THEN
File collapseSpecFile = folder.resolve("target/generated-sources/common-maven/remote-openapi/petstore-full-spec.yaml").toFile();
assertTrue(collapseSpecFile.exists());
assertTrue(Files.exists(
tempDir.resolve("target/generated-sources/common-maven/remote-openapi/petstore-full-spec.yaml")
));
}
public void testCollapsedSpecAddedToArtifacts() throws Exception {
// GIVEN
Path folder = Files.createTempDirectory("test");
CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/default", "file", "executionId");
CodeGenMojo mojo = loadMojo(newTempFolder(), "src/test/resources/default", "file", "executionId");
// WHEN
mojo.execute();
@ -201,8 +197,7 @@ public class CodeGenMojoTest extends BaseTestCase {
public void testAnyInputSpecMustBeProvided() throws Exception {
// GIVEN
Path folder = Files.createTempDirectory("test");
CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/default", "file", "executionId");
CodeGenMojo mojo = loadMojo(newTempFolder(), "src/test/resources/default", "file", "executionId");
mojo.inputSpec = null;
mojo.inputSpecRootDirectory = null;
@ -215,8 +210,8 @@ public class CodeGenMojoTest extends BaseTestCase {
public void testInputSpecRootDirectoryDoesNotRequireInputSpec() throws Exception {
// GIVEN
Path folder = Files.createTempDirectory("test");
CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/default", "file", "executionId");
final Path tempDir = newTempFolder();
CodeGenMojo mojo = loadMojo(tempDir, "src/test/resources/default", "file", "executionId");
mojo.inputSpec = null;
mojo.inputSpecRootDirectory = "src/test/resources/default";
@ -225,17 +220,43 @@ public class CodeGenMojoTest extends BaseTestCase {
// THEN
/* Check the hash file was created */
final Path hashFolder = folder.resolve("target/generated-sources/common-maven/remote-openapi/.openapi-generator");
assertTrue(hashFolder.resolve("_merged_spec.yaml-executionId.sha256").toFile().exists());
final Path hashFolder = tempDir.resolve("target/generated-sources/common-maven/remote-openapi/.openapi-generator");
assertTrue(Files.exists(hashFolder.resolve("_merged_spec.yaml-executionId.sha256")));
}
protected CodeGenMojo loadMojo(File temporaryFolder, String projectRoot, String profile) throws Exception {
/**
* Regression test for <a href="https://github.com/OpenAPITools/openapi-generator/issues/16489">#16489</a>
*/
public void test_skipIfSpecIsUnchanged_recognizesUpdatesInExternalReferencedFile() throws Exception {
//GIVEN
final Path tempDir = newTempFolder();
final Path generatedDir = tempDir.resolve("target/generated-sources/issue-16489");
final Path hashFile = generatedDir.resolve(".openapi-generator/petstore.yaml-default.sha256");
final CodeGenMojo mojo = loadMojo(tempDir, "src/test/resources/issue-16489", null);
mojo.execute(); // Perform an initial generation
var currentHash = Files.readString(hashFile); // read hash
FileUtils.deleteDirectory(generatedDir.resolve("src").toFile()); // Remove the generated source
Files.writeString( // change schema definition in external file
tempDir.resolve("schemas/Pet.yaml"),"\n wrapped: true", StandardOpenOption.APPEND
);
// WHEN
mojo.execute(); // Execute the mojo again
// THEN
assertNotEquals(
Files.readString(hashFile), currentHash, "Checksum should not be the same after external file change"
);
assertTrue("Src directory should have been regenerated", Files.exists(generatedDir.resolve("src")));
}
protected CodeGenMojo loadMojo(Path temporaryFolder, String projectRoot, String profile) throws Exception {
return loadMojo(temporaryFolder, projectRoot, profile, "default");
}
protected CodeGenMojo loadMojo(File temporaryFolder, String projectRoot, String profile, String executionId) throws Exception {
File file = new File(projectRoot);
FileUtils.copyDirectory(file, temporaryFolder);
protected CodeGenMojo loadMojo(Path temporaryFolder, String projectRoot, String profile, String executionId) throws Exception {
FileUtils.copyDirectory(new File(projectRoot), temporaryFolder.toFile());
MavenProject project = readMavenProject(temporaryFolder, profile);
MavenSession session = newMavenSession(project);
MojoExecution execution = newMojoExecution("generate");
@ -249,22 +270,29 @@ public class CodeGenMojoTest extends BaseTestCase {
return executionWithId;
}
protected MavenProject readMavenProject(File basedir, String profile)
throws Exception {
File pom = new File(basedir, "pom.xml");
LocalRepository localRepo = new LocalRepository(new File(basedir, "local-repo"));
protected MavenProject readMavenProject(Path basedir, String profile) throws Exception {
LocalRepository localRepo = new LocalRepository(basedir.resolve("local-repo").toFile());
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
session.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory().newInstance(session, localRepo));
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
request.setBaseDirectory(basedir);
session.setLocalRepositoryManager(
new SimpleLocalRepositoryManagerFactory(new DefaultLocalPathComposer()).newInstance(session, localRepo)
);
MavenExecutionRequest request = new DefaultMavenExecutionRequest().setBaseDirectory(basedir.toFile());
if (profile != null) {
request.addActiveProfile(profile);
}
ProjectBuildingRequest configuration = request.getProjectBuildingRequest();
configuration.setRepositorySession(session);
configuration.setResolveDependencies(true);
MavenProject project = lookup(ProjectBuilder.class).build(pom, configuration).getProject();
ProjectBuildingRequest configuration = request.getProjectBuildingRequest()
.setRepositorySession(session)
.setResolveDependencies(true);
MavenProject project = lookup(ProjectBuilder.class)
.build(basedir.resolve("pom.xml").toFile(), configuration)
.getProject();
assertNotNull(project);
return project;
}
static private Path newTempFolder() throws IOException {
final Path tempDir = Files.createTempDirectory("test");
tempDir.toFile().deleteOnExit();
return tempDir;
}
}

View File

@ -0,0 +1,105 @@
openapi: 3.0.0
servers:
- url: 'http://petstore.swagger.io/v2'
info:
description: Sample file with just two endpoints and one schema (defined in an external file $ref)
version: 1.0.0
title: OpenAPI Petstore
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
$ref: '#/components/requestBodies/Pet'
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
delete:
tags:
- pet
summary: Deletes a pet
description: ''
operationId: deletePet
parameters:
- name: api_key
in: header
required: false
schema:
type: string
- name: petId
in: path
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
'400':
description: Invalid pet value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
components:
requestBodies:
Pet:
content:
application/json:
schema:
$ref: 'schemas/Pet.yaml'
application/xml:
schema:
$ref: 'schemas/Pet.yaml'
description: Pet object that needs to be added to the store
required: true
schemas:
Pet:
$ref: 'schemas/Pet.yaml'

View File

@ -0,0 +1,61 @@
<!--
~ Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>common.maven</groupId>
<artifactId>issue-16489</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>OpenAPI Generator Configuration Test</name>
<url>https://openapi-generator.tech/</url>
<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.6.0</version>
<configuration>
<generatorName>java</generatorName>
<skipIfSpecIsUnchanged>true</skipIfSpecIsUnchanged>
<library>native</library>
<output>${basedir}/target/generated-sources/issue-16489</output>
<additionalProperties>hideGenerationTimestamp=true</additionalProperties>
<inputSpec>${basedir}/petstore.yaml</inputSpec>
<generateModelTests>false</generateModelTests>
<generateModelDocumentation>false</generateModelDocumentation>
<generateApiTests>false</generateApiTests>
<generateApis>false</generateApis>
<generateSupportingFiles>false</generateSupportingFiles>
<configOptions>
<interfaceOnly>true</interfaceOnly>
</configOptions>
</configuration>
<executions>
<execution>
<id>generate</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,29 @@
title: a Pet
description: A pet for sale in the pet store
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
name:
type: string
example: doggie
photoUrls:
type: array
xml:
name: photoUrl
wrapped: true
items:
type: string
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: Pet