Skip to content
Permalink
Browse files

[kotlin] [bugfix] [maven-plugin]: prevent ClassCastException with boo…

…lean config options (#4361)

* fix: prevent classcast exception during execution of openapi-generator-maven-plugin.

* style: revert styling to openapi defaults

* test: unit test coverage for handling boolean config options

* fix: replace option value with boolean, if it is a string literal boolean

* style: use data type long

* test: add maven testfile kotlin.xml to travis build

* test: runnable maven test of the kotlin generator
  • Loading branch information...
janweinschenker authored and wing328 committed Nov 8, 2019
1 parent b0b0e2b commit f9af3c27527c147c5dea937818d306bb0f350ab8
@@ -138,6 +138,7 @@ script:
# test maven plugin
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/java-client.xml
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/multi-module/pom.xml
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/kotlin.xml
# test gradle plugin
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew buildGoSdk)
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew openApiGenerate)
@@ -0,0 +1,237 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>sample-project</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>sample-project</name>
<url>http://maven.apache.org</url>

<build>
<plugins>
<!-- activate the plugin -->
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>4.2.1-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<id>default</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- specify the swagger yaml -->
<inputSpec>${project.basedir}/swagger.yaml</inputSpec>

<!-- target to generate java client code -->
<generatorName>kotlin</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> -->

<!-- pass any necessary config options -->
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>

</configuration>
</execution>
<execution>
<id>kotlin</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- specify the swagger yaml -->
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml
</inputSpec>

<!-- target to generate java client code -->
<generatorName>kotlin</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> -->

<!-- pass any necessary config options -->
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>

<output>${project.build.directory}/generated-sources/kotlin</output>
<apiPackage>kotlintest.org.openapitools.client.api</apiPackage>
<modelPackage>kotlintest.org.openapitools.client.model</modelPackage>
<invokerPackage>kotlintest.org.openapitools.client</invokerPackage>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<proc>none</proc>
</configuration>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<jvmTarget>${kotlinJvmTarget}</jvmTarget>
<javacOptions/>
</configuration>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.build.directory}/generated-sources/kotlin/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<pluginRepositories>
<pluginRepository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<!-- dependencies are needed for the client being generated -->

<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>

<!-- You can find the dependencies for the library configuation you chose by looking in JavaClientCodegen.
Then find the corresponding dependency on Maven Central, and set the versions in the property section below -->

<!-- HTTP client: jersey-client -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey-version}</version>
</dependency>

<!-- @Nullable annotation -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>

<!-- JSON processing: jackson -->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>${jackson-databind-nullable-version}</version>
</dependency>

<!-- Joda time: if you use it -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime-version}</version>
</dependency>

<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>${migbase64.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-kotlin</artifactId>
<version>${moshi-kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-adapters</artifactId>
<version>${moshi-kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.2.2</version>
</dependency>
</dependencies>

<properties>
<swagger-annotations-version>1.5.8</swagger-annotations-version>
<jersey-version>2.27</jersey-version>
<jackson-version>2.8.9</jackson-version>
<jackson-databind-nullable-version>0.2.0</jackson-databind-nullable-version>
<jodatime-version>2.7</jodatime-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.8.1</junit-version>
<kotlin.version>1.3.50</kotlin.version>
<kotlinJvmTarget>1.8</kotlinJvmTarget>
<moshi-kotlin.version>1.8.0</moshi-kotlin.version>
<migbase64.version>2.2</migbase64.version>
</properties>
</project>
@@ -434,19 +434,19 @@ public void processOpts() {
}

if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) {
this.setSerializableModel(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL)));
this.setSerializableModel(getBooleanOption(CodegenConstants.SERIALIZABLE_MODEL));
} else {
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
}

if (additionalProperties.containsKey(CodegenConstants.PARCELIZE_MODELS)) {
this.setParcelizeModels(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.PARCELIZE_MODELS)));
this.setParcelizeModels(getBooleanOption(CodegenConstants.PARCELIZE_MODELS));
} else {
additionalProperties.put(CodegenConstants.PARCELIZE_MODELS, parcelizeModels);
}

if (additionalProperties.containsKey(CodegenConstants.NON_PUBLIC_API)) {
this.setNonPublicApi(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.NON_PUBLIC_API)));
this.setNonPublicApi(getBooleanOption(CodegenConstants.NON_PUBLIC_API));
} else {
additionalProperties.put(CodegenConstants.NON_PUBLIC_API, nonPublicApi);
}
@@ -458,6 +458,18 @@ public void processOpts() {
additionalProperties.put("modelDocPath", modelDocPath);
}

private boolean getBooleanOption(String key) {
final Object booleanValue = additionalProperties.get(key);
Boolean result = Boolean.FALSE;
if (booleanValue instanceof Boolean) {
result = (Boolean) booleanValue;
} else if (booleanValue instanceof String) {
result = Boolean.parseBoolean((String) booleanValue);
}
additionalProperties.put(key, result);
return result;
}

public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
@@ -501,7 +513,7 @@ public boolean isSerializableModel() {
public void setSerializableModel(boolean serializableModel) {
this.serializableModel = serializableModel;
}

public boolean nonPublicApi() {
return nonPublicApi;
}
@@ -1,5 +1,6 @@
package org.openapitools.codegen.kotlin;

import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.languages.AbstractKotlinCodegen;
import org.testng.Assert;
@@ -53,7 +54,7 @@ public void pascalCaseEnumConverter() {
}

@Test
public void toEnumValue(){
public void toEnumValue() {
assertEquals(codegen.toEnumValue("1", "kotlin.Int"), "1");
assertEquals(codegen.toEnumValue("1", "kotlin.Double"), "1.0");
assertEquals(codegen.toEnumValue("1.3", "kotlin.Double"), "1.3");
@@ -81,14 +82,14 @@ public String getHelp() {
}

@Test
public void isDataTypeString(){
public void isDataTypeString() {
assertFalse(codegen.isDataTypeString("kotlin.Int"));
assertTrue(codegen.isDataTypeString("kotlin.String"));
assertTrue(codegen.isDataTypeString("String"));
}

@Test
public void toModelNameShouldUseProvidedMapping() {
public void toModelNameShouldUseProvidedMapping() {
codegen.importMapping().put("json_myclass", "com.test.MyClass");
assertEquals("com.test.MyClass", codegen.toModelName("json_myclass"));
}
@@ -155,5 +156,45 @@ public void apiTestFileFolder() {
Assert.assertEquals(codegen.apiTestFileFolder(), "/User/open/api/tools/test/folder/org/openapitools/codegen/api".replace('/', File.separatorChar));
}

@Test
public void processOptsBooleanTrueFromString() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "true");
codegen.processOpts();
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanTrueFromBoolean() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, true);
codegen.processOpts();
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromString() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "false");
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromBoolean() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, false);
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromGarbage() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "blibb");
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromNumeric() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, 42L);
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
}

0 comments on commit f9af3c2

Please sign in to comment.
You can’t perform that action at this time.