Skip to content

Commit

Permalink
[bug][maven] Fix custom windows classpaths in maven plugin (#7587)
Browse files Browse the repository at this point in the history
* [maven] Fallback to templates using classpath rather than OS-specific paths

Previous checks would cause logic in Windows to return early, for
built-in templates only. This reorganizes and simplifies the ordering
behavior.

* Match classpath check in WorkflowSettings with that in TemplateManager

* [maven] Much needed unit/integration tests

This follows similar approach used in PMD and other plugins managed by
maven.

Unit tests simply verify we can load configuration as expected into the
Mojo.

Integration tests execute actual sample projects bound to the current
build's Maven plugin. This uses maven-invoker-plugin, which also allows
for specifying the maven options in invoker.properties to execute the test.
It also provides a verification framework using groovy files with the
required naming convention of "verify.groovy". This allows us to quickly
and easily check that certain files are outputted by generation, and we
may also spotcheck file contents.

templateResourcePath option is skipped on windows. I've tested back to
version 3.3.3 and this doesn't seem to have worked consistently with how
the property works on non-Windows.

* Set groovy 3.0.5 for test harness

* Print stacktrace on Maven error in Travis

* [maven] Set groovy version in tests to supported in Java 11+

* Puts maven integration tests in separate profile called 'integration'
  • Loading branch information
jimschubert authored Oct 18, 2020
1 parent 34d2e25 commit ee1cbf6
Show file tree
Hide file tree
Showing 21 changed files with 1,518 additions and 10 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ script:
- /bin/bash ./bin/utils/detect_tab_in_java_class.sh
# run integration tests defined in maven pom.xml
# WARN: Travis will timeout after 10 minutes of no stdout/stderr activity, which is problematic with mvn --quiet.
- mvn --no-snapshot-updates --quiet --batch-mode --show-version clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- mvn --no-snapshot-updates --quiet --batch-mode --show-version verify -Psamples -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- mvn -e --no-snapshot-updates --quiet --batch-mode --show-version clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- mvn -e --no-snapshot-updates --quiet --batch-mode --show-version verify -Psamples -Dorg.slf4j.simpleLogger.defaultLogLevel=error
after_success:
# push to maven repo
- if [ $SONATYPE_USERNAME ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;

/**
* Represents those settings applied to a generation workflow.
Expand Down Expand Up @@ -444,10 +445,20 @@ public Builder withTemplateDir(String templateDir) {
uri = f.toURI();
this.templateDir = Paths.get(uri).toAbsolutePath().normalize().toString();
} else {
URL url = this.getClass().getClassLoader().getResource(templateDir);
String cpDir;
// HACK: this duplicates TemplateManager.getCPResourcePath a bit. We should probably move that function to core.
if (!"/".equals(File.separator)) {
// Windows users may pass path specific to OS, but classpath must be "/" separators
cpDir = templateDir.replaceAll(Pattern.quote(File.separator), "/");
} else {
cpDir = templateDir;
}

URL url = this.getClass().getClassLoader().getResource(cpDir);
if (url != null) {
try {
uri = url.toURI();
// we can freely set to templateDir here and allow templating to manage template lookups
this.templateDir = templateDir;
} catch (URISyntaxException e) {
LOGGER.warn("The requested template was found on the classpath, but resulted in a syntax error.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@
<!-- target to generate java client code -->
<generatorName>java</generatorName>

<!-- hint: if you want to generate java server code, e.g. based on Spring Boot,
you can use the following target: <generatorName>spring</generatorName> -->
<templateDirectory>${project.basedir}/templates</templateDirectory>

<!-- pass any necessary config options -->
<configOptions>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# TEST TEST TEST

# {{artifactId}}

{{appName}}

- API version: {{appVersion}}
{{^hideGenerationTimestamp}}

- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}

{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}}

{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}

*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*

… etc.
56 changes: 55 additions & 1 deletion modules/openapi-generator-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.exclusions>**/src/main/java/org/openapitools/codegen/plugin/**/*</sonar.exclusions>
<!-- used for integration tests verification scripts, managed by the test harness plugin -->
<groovy.version>3.0.5</groovy.version>
</properties>
<dependencies>
<dependency>
Expand Down Expand Up @@ -60,6 +62,24 @@
<!-- <version>4.12</version> -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-verifier</artifactId>
<version>1.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
Expand Down Expand Up @@ -108,7 +128,41 @@
</plugins>
</build>
<profiles>

<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<postBuildHookScript>verify</postBuildHookScript>
<showVersion>true</showVersion>
<streamLogs>true</streamLogs>
<noLog>false</noLog>
<showErrors>true</showErrors>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>static-analysis</id>
<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
invoker.goals = -nsu generate-sources
invoker.name = Test Custom Templates via Resource
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.openapitools.maven.its</groupId>
<artifactId>custom-template-resource</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<configuration>
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml</inputSpec>
<generatorName>kotlin</generatorName>
<output>${basedir}/out</output>
<!--
HACK: rather than compile our own resource, we'll pull from something that's already available: bash generator's templates
This only works because bash shares only README.mustache template with kotlin
-->
<templateResourcePath>bash</templateResourcePath>
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.
*/

File readme = new File(basedir, "out/README.md")

assert readme.isFile()
if (File.separator == "/") {
// For whatever reason, resource path templates fail in this test in Windows
assert readme.text.contains("# OpenAPI Petstore Bash client")
}

File gradle = new File(basedir, "out/build.gradle")
assert gradle.isFile()

File api = new File(basedir, "out/src/main/kotlin/org/openapitools/client/apis/PetApi.kt")
assert api.isFile()

File model = new File(basedir, "out/src/main/kotlin/org/openapitools/client/models/Pet.kt")
assert model.isFile()

// note that in Java 11+, this anything matching this condition could fail due to
// Illegal reflective access by org.codehaus.groovy.reflection.CachedClass
// and cause tests to fail. This is more to document for engineers.
if (GroovySystem.version.tokenize('.')[0].toInteger() < 3) {
throw new IllegalStateException("Found:" + GroovySystem.version + ", need Groovy 3.x or higher for Java 11+, so we require it for all versions")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
invoker.goals = -nsu generate-sources
invoker.name = Test Custom Templates
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.openapitools.maven.its</groupId>
<artifactId>custom-template</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<configuration>
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml</inputSpec>
<generatorName>kotlin</generatorName>
<output>${basedir}/out</output>
<templateDirectory>${project.basedir}/templates</templateDirectory>
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>
</configuration>
<executions>
<execution>
<id>remote</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# TEST TEST TEST

# {{artifactId}}

{{appName}}

- API version: {{appVersion}}
{{^hideGenerationTimestamp}}

- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}

{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}}

{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}

*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*

… etc.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.
*/

File readme = new File(basedir, "out/README.md")

assert readme.isFile()
assert readme.text.contains("# TEST TEST TEST")
assert readme.text.contains("# kotlin-client")
assert readme.text.contains("OpenAPI Petstore")

File gradle = new File(basedir, "out/build.gradle")
assert gradle.isFile()

File api = new File(basedir, "out/src/main/kotlin/org/openapitools/client/apis/PetApi.kt")
assert api.isFile()

File model = new File(basedir, "out/src/main/kotlin/org/openapitools/client/models/Pet.kt")
assert model.isFile()

// note that in Java 11+, this anything matching this condition could fail due to
// Illegal reflective access by org.codehaus.groovy.reflection.CachedClass
// and cause tests to fail. This is more to document for engineers.
if (GroovySystem.version.tokenize('.')[0].toInteger() < 3) {
throw new IllegalStateException("Found:" + GroovySystem.version + ", need Groovy 3.x or higher for Java 11+, so we require it for all versions")
}
Loading

0 comments on commit ee1cbf6

Please sign in to comment.