Skip to content

Commit f9af3c2

Browse files
janweinschenkerwing328
authored andcommitted
[kotlin] [bugfix] [maven-plugin]: prevent ClassCastException with boolean 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
1 parent b0b0e2b commit f9af3c2

File tree

4 files changed

+298
-7
lines changed

4 files changed

+298
-7
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ script:
138138
# test maven plugin
139139
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/java-client.xml
140140
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/multi-module/pom.xml
141+
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/kotlin.xml
141142
# test gradle plugin
142143
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew buildGoSdk)
143144
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew openApiGenerate)
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>org.openapitools</groupId>
5+
<artifactId>sample-project</artifactId>
6+
<packaging>jar</packaging>
7+
<version>1.0-SNAPSHOT</version>
8+
<name>sample-project</name>
9+
<url>http://maven.apache.org</url>
10+
11+
<build>
12+
<plugins>
13+
<!-- activate the plugin -->
14+
<plugin>
15+
<groupId>org.openapitools</groupId>
16+
<artifactId>openapi-generator-maven-plugin</artifactId>
17+
<!-- RELEASE_VERSION -->
18+
<version>4.2.1-SNAPSHOT</version>
19+
<!-- /RELEASE_VERSION -->
20+
<executions>
21+
<execution>
22+
<id>default</id>
23+
<goals>
24+
<goal>generate</goal>
25+
</goals>
26+
<configuration>
27+
<!-- specify the swagger yaml -->
28+
<inputSpec>${project.basedir}/swagger.yaml</inputSpec>
29+
30+
<!-- target to generate java client code -->
31+
<generatorName>kotlin</generatorName>
32+
33+
<!-- hint: if you want to generate java server code, e.g. based on Spring Boot,
34+
you can use the following target: <generatorName>spring</generatorName> -->
35+
36+
<!-- pass any necessary config options -->
37+
<configOptions>
38+
<serializableModel>true</serializableModel>
39+
</configOptions>
40+
41+
</configuration>
42+
</execution>
43+
<execution>
44+
<id>kotlin</id>
45+
<phase>generate-sources</phase>
46+
<goals>
47+
<goal>generate</goal>
48+
</goals>
49+
<configuration>
50+
<!-- specify the swagger yaml -->
51+
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml
52+
</inputSpec>
53+
54+
<!-- target to generate java client code -->
55+
<generatorName>kotlin</generatorName>
56+
57+
<!-- hint: if you want to generate java server code, e.g. based on Spring Boot,
58+
you can use the following target: <generatorName>spring</generatorName> -->
59+
60+
<!-- pass any necessary config options -->
61+
<configOptions>
62+
<serializableModel>true</serializableModel>
63+
</configOptions>
64+
65+
<output>${project.build.directory}/generated-sources/kotlin</output>
66+
<apiPackage>kotlintest.org.openapitools.client.api</apiPackage>
67+
<modelPackage>kotlintest.org.openapitools.client.model</modelPackage>
68+
<invokerPackage>kotlintest.org.openapitools.client</invokerPackage>
69+
</configuration>
70+
</execution>
71+
</executions>
72+
</plugin>
73+
<plugin>
74+
<groupId>org.apache.maven.plugins</groupId>
75+
<artifactId>maven-compiler-plugin</artifactId>
76+
<version>3.8.1</version>
77+
<configuration>
78+
<source>1.8</source>
79+
<target>1.8</target>
80+
<proc>none</proc>
81+
</configuration>
82+
</plugin>
83+
<plugin>
84+
<artifactId>kotlin-maven-plugin</artifactId>
85+
<groupId>org.jetbrains.kotlin</groupId>
86+
<configuration>
87+
<jvmTarget>${kotlinJvmTarget}</jvmTarget>
88+
<javacOptions/>
89+
</configuration>
90+
<executions>
91+
<execution>
92+
<id>compile</id>
93+
<goals>
94+
<goal>compile</goal>
95+
</goals>
96+
<configuration>
97+
<sourceDirs>
98+
<sourceDir>${project.build.directory}/generated-sources/kotlin/src/main/kotlin</sourceDir>
99+
</sourceDirs>
100+
</configuration>
101+
</execution>
102+
</executions>
103+
</plugin>
104+
</plugins>
105+
<pluginManagement>
106+
<plugins>
107+
<plugin>
108+
<artifactId>kotlin-maven-plugin</artifactId>
109+
<groupId>org.jetbrains.kotlin</groupId>
110+
<version>${kotlin.version}</version>
111+
</plugin>
112+
</plugins>
113+
</pluginManagement>
114+
</build>
115+
<pluginRepositories>
116+
<pluginRepository>
117+
<id>sonatype-snapshots</id>
118+
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
119+
</pluginRepository>
120+
</pluginRepositories>
121+
<dependencies>
122+
<!-- dependencies are needed for the client being generated -->
123+
124+
<dependency>
125+
<groupId>io.swagger</groupId>
126+
<artifactId>swagger-annotations</artifactId>
127+
<version>${swagger-annotations-version}</version>
128+
</dependency>
129+
130+
<!-- You can find the dependencies for the library configuation you chose by looking in JavaClientCodegen.
131+
Then find the corresponding dependency on Maven Central, and set the versions in the property section below -->
132+
133+
<!-- HTTP client: jersey-client -->
134+
<dependency>
135+
<groupId>org.glassfish.jersey.core</groupId>
136+
<artifactId>jersey-client</artifactId>
137+
<version>${jersey-version}</version>
138+
</dependency>
139+
<dependency>
140+
<groupId>org.glassfish.jersey.media</groupId>
141+
<artifactId>jersey-media-multipart</artifactId>
142+
<version>${jersey-version}</version>
143+
</dependency>
144+
<dependency>
145+
<groupId>org.glassfish.jersey.media</groupId>
146+
<artifactId>jersey-media-json-jackson</artifactId>
147+
<version>${jersey-version}</version>
148+
</dependency>
149+
150+
<!-- @Nullable annotation -->
151+
<dependency>
152+
<groupId>com.google.code.findbugs</groupId>
153+
<artifactId>jsr305</artifactId>
154+
<version>3.0.2</version>
155+
</dependency>
156+
157+
<!-- JSON processing: jackson -->
158+
<dependency>
159+
<groupId>com.fasterxml.jackson.jaxrs</groupId>
160+
<artifactId>jackson-jaxrs-base</artifactId>
161+
<version>${jackson-version}</version>
162+
</dependency>
163+
<dependency>
164+
<groupId>com.fasterxml.jackson.core</groupId>
165+
<artifactId>jackson-core</artifactId>
166+
<version>${jackson-version}</version>
167+
</dependency>
168+
<dependency>
169+
<groupId>com.fasterxml.jackson.core</groupId>
170+
<artifactId>jackson-annotations</artifactId>
171+
<version>${jackson-version}</version>
172+
</dependency>
173+
<dependency>
174+
<groupId>com.fasterxml.jackson.core</groupId>
175+
<artifactId>jackson-databind</artifactId>
176+
<version>${jackson-version}</version>
177+
</dependency>
178+
<dependency>
179+
<groupId>com.fasterxml.jackson.jaxrs</groupId>
180+
<artifactId>jackson-jaxrs-json-provider</artifactId>
181+
<version>${jackson-version}</version>
182+
</dependency>
183+
<dependency>
184+
<groupId>org.openapitools</groupId>
185+
<artifactId>jackson-databind-nullable</artifactId>
186+
<version>${jackson-databind-nullable-version}</version>
187+
</dependency>
188+
189+
<!-- Joda time: if you use it -->
190+
<dependency>
191+
<groupId>com.fasterxml.jackson.datatype</groupId>
192+
<artifactId>jackson-datatype-joda</artifactId>
193+
<version>${jackson-version}</version>
194+
</dependency>
195+
<dependency>
196+
<groupId>joda-time</groupId>
197+
<artifactId>joda-time</artifactId>
198+
<version>${jodatime-version}</version>
199+
</dependency>
200+
201+
<!-- Base64 encoding that works in both JVM and Android -->
202+
<dependency>
203+
<groupId>com.brsanthu</groupId>
204+
<artifactId>migbase64</artifactId>
205+
<version>${migbase64.version}</version>
206+
</dependency>
207+
<dependency>
208+
<groupId>com.squareup.moshi</groupId>
209+
<artifactId>moshi-kotlin</artifactId>
210+
<version>${moshi-kotlin.version}</version>
211+
</dependency>
212+
<dependency>
213+
<groupId>com.squareup.moshi</groupId>
214+
<artifactId>moshi-adapters</artifactId>
215+
<version>${moshi-kotlin.version}</version>
216+
</dependency>
217+
<dependency>
218+
<groupId>com.squareup.okhttp3</groupId>
219+
<artifactId>okhttp</artifactId>
220+
<version>4.2.2</version>
221+
</dependency>
222+
</dependencies>
223+
224+
<properties>
225+
<swagger-annotations-version>1.5.8</swagger-annotations-version>
226+
<jersey-version>2.27</jersey-version>
227+
<jackson-version>2.8.9</jackson-version>
228+
<jackson-databind-nullable-version>0.2.0</jackson-databind-nullable-version>
229+
<jodatime-version>2.7</jodatime-version>
230+
<maven-plugin-version>1.0.0</maven-plugin-version>
231+
<junit-version>4.8.1</junit-version>
232+
<kotlin.version>1.3.50</kotlin.version>
233+
<kotlinJvmTarget>1.8</kotlinJvmTarget>
234+
<moshi-kotlin.version>1.8.0</moshi-kotlin.version>
235+
<migbase64.version>2.2</migbase64.version>
236+
</properties>
237+
</project>

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -434,19 +434,19 @@ public void processOpts() {
434434
}
435435

436436
if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) {
437-
this.setSerializableModel(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL)));
437+
this.setSerializableModel(getBooleanOption(CodegenConstants.SERIALIZABLE_MODEL));
438438
} else {
439439
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
440440
}
441441

442442
if (additionalProperties.containsKey(CodegenConstants.PARCELIZE_MODELS)) {
443-
this.setParcelizeModels(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.PARCELIZE_MODELS)));
443+
this.setParcelizeModels(getBooleanOption(CodegenConstants.PARCELIZE_MODELS));
444444
} else {
445445
additionalProperties.put(CodegenConstants.PARCELIZE_MODELS, parcelizeModels);
446446
}
447447

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

461+
private boolean getBooleanOption(String key) {
462+
final Object booleanValue = additionalProperties.get(key);
463+
Boolean result = Boolean.FALSE;
464+
if (booleanValue instanceof Boolean) {
465+
result = (Boolean) booleanValue;
466+
} else if (booleanValue instanceof String) {
467+
result = Boolean.parseBoolean((String) booleanValue);
468+
}
469+
additionalProperties.put(key, result);
470+
return result;
471+
}
472+
461473
public void setArtifactId(String artifactId) {
462474
this.artifactId = artifactId;
463475
}
@@ -501,7 +513,7 @@ public boolean isSerializableModel() {
501513
public void setSerializableModel(boolean serializableModel) {
502514
this.serializableModel = serializableModel;
503515
}
504-
516+
505517
public boolean nonPublicApi() {
506518
return nonPublicApi;
507519
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.openapitools.codegen.kotlin;
22

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

5556
@Test
56-
public void toEnumValue(){
57+
public void toEnumValue() {
5758
assertEquals(codegen.toEnumValue("1", "kotlin.Int"), "1");
5859
assertEquals(codegen.toEnumValue("1", "kotlin.Double"), "1.0");
5960
assertEquals(codegen.toEnumValue("1.3", "kotlin.Double"), "1.3");
@@ -81,14 +82,14 @@ public String getHelp() {
8182
}
8283

8384
@Test
84-
public void isDataTypeString(){
85+
public void isDataTypeString() {
8586
assertFalse(codegen.isDataTypeString("kotlin.Int"));
8687
assertTrue(codegen.isDataTypeString("kotlin.String"));
8788
assertTrue(codegen.isDataTypeString("String"));
8889
}
8990

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

159+
@Test
160+
public void processOptsBooleanTrueFromString() {
161+
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "true");
162+
codegen.processOpts();
163+
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
164+
}
165+
166+
@Test
167+
public void processOptsBooleanTrueFromBoolean() {
168+
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, true);
169+
codegen.processOpts();
170+
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
171+
}
172+
173+
@Test
174+
public void processOptsBooleanFalseFromString() {
175+
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "false");
176+
codegen.processOpts();
177+
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
178+
}
158179

180+
@Test
181+
public void processOptsBooleanFalseFromBoolean() {
182+
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, false);
183+
codegen.processOpts();
184+
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
185+
}
186+
187+
@Test
188+
public void processOptsBooleanFalseFromGarbage() {
189+
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "blibb");
190+
codegen.processOpts();
191+
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
192+
}
193+
194+
@Test
195+
public void processOptsBooleanFalseFromNumeric() {
196+
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, 42L);
197+
codegen.processOpts();
198+
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
199+
}
159200
}

0 commit comments

Comments
 (0)