Skip to content

Commit

Permalink
[kotlin] Map file and binary to ByteArray (#19840)
Browse files Browse the repository at this point in the history
* [kotlin] Map file and binary to ByteArray

* [kotlin] Map file and binary to ByteArray
  • Loading branch information
4brunu authored Oct 11, 2024
1 parent 185c063 commit 462f450
Show file tree
Hide file tree
Showing 26 changed files with 358 additions and 5 deletions.
1 change: 1 addition & 0 deletions bin/configs/kotlin-string.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ templateDir: modules/openapi-generator/src/main/resources/kotlin-client
additionalProperties:
artifactId: kotlin-petstore-string
serializableModel: "true"
mapFileBinaryToByteArray: "true"
sortModelPropertiesByRequiredFlag: "false"
sortParamsByRequiredFlag: "false"
dateLibrary: string
1 change: 1 addition & 0 deletions docs/generators/kotlin.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|idea|Add IntellJ Idea plugin and mark Kotlin main and test folders as source folders.| |false|
|library|Library template (sub-template) to use|<dl><dt>**jvm-ktor**</dt><dd>Platform: Java Virtual Machine. HTTP client: Ktor 1.6.7. JSON processing: Gson, Jackson (default).</dd><dt>**jvm-okhttp4**</dt><dd>[DEFAULT] Platform: Java Virtual Machine. HTTP client: OkHttp 4.2.0 (Android 5.0+ and Java 8+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-spring-webclient**</dt><dd>Platform: Java Virtual Machine. HTTP: Spring 5 (or 6 with useSpringBoot3 enabled) WebClient. JSON processing: Jackson.</dd><dt>**jvm-spring-restclient**</dt><dd>Platform: Java Virtual Machine. HTTP: Spring 6 RestClient. JSON processing: Jackson.</dd><dt>**jvm-retrofit2**</dt><dd>Platform: Java Virtual Machine. HTTP client: Retrofit 2.6.2.</dd><dt>**multiplatform**</dt><dd>Platform: Kotlin multiplatform. HTTP client: Ktor 1.6.7. JSON processing: Kotlinx Serialization: 1.2.1.</dd><dt>**jvm-volley**</dt><dd>Platform: JVM for Android. HTTP client: Volley 1.2.1. JSON processing: gson 2.8.9</dd><dt>**jvm-vertx**</dt><dd>Platform: Java Virtual Machine. HTTP client: Vert.x Web Client. JSON processing: Moshi, Gson or Jackson.</dd></dl>|jvm-okhttp4|
|mapFileBinaryToByteArray|Map File and Binary to ByteArray (default: false)| |false|
|modelMutable|Create mutable models| |false|
|moshiCodeGen|Whether to enable codegen with the Moshi library. Refer to the [official Moshi doc](https://github.com/square/moshi#codegen) for more info.| |false|
|nullableReturnType|Nullable return type| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,13 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {

public static final String SUPPORT_ANDROID_API_LEVEL_25_AND_BELLOW = "supportAndroidApiLevel25AndBelow";

public static final String MAP_FILE_BINARY_TO_BYTE_ARRAY = "mapFileBinaryToByteArray";

public static final String GENERATE_ONEOF_ANYOF_WRAPPERS = "generateOneOfAnyOfWrappers";

protected static final String VENDOR_EXTENSION_BASE_NAME_LITERAL = "x-base-name-literal";


@Setter protected String dateLibrary = DateLibrary.JAVA8.value;
@Setter protected String requestDateConverter = RequestDateConverter.TO_JSON.value;
@Setter protected String collectionType = CollectionType.LIST.value;
Expand All @@ -108,6 +111,7 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
protected boolean generateRoomModels = false;
@Setter protected String roomModelPackage = "";
@Setter protected boolean omitGradleWrapper = false;
@Setter protected boolean mapFileBinaryToByteArray = false;
@Setter protected boolean generateOneOfAnyOfWrappers = true;
@Getter @Setter protected boolean failOnUnknownProperties = false;

Expand Down Expand Up @@ -269,6 +273,8 @@ public KotlinClientCodegen() {

cliOptions.add(CliOption.newBoolean(SUPPORT_ANDROID_API_LEVEL_25_AND_BELLOW, "[WARNING] This flag will generate code that has a known security vulnerability. It uses `kotlin.io.createTempFile` instead of `java.nio.file.Files.createTempFile` in order to support Android API level 25 and bellow. For more info, please check the following links https://github.com/OpenAPITools/openapi-generator/security/advisories/GHSA-23x4-m842-fmwf, https://github.com/OpenAPITools/openapi-generator/pull/9284"));

cliOptions.add(new CliOption(MAP_FILE_BINARY_TO_BYTE_ARRAY, "Map File and Binary to ByteArray (default: false)").defaultValue(Boolean.FALSE.toString()));

cliOptions.add(CliOption.newBoolean(GENERATE_ONEOF_ANYOF_WRAPPERS, "Generate oneOf, anyOf schemas as wrappers."));

CliOption serializationLibraryOpt = new CliOption(CodegenConstants.SERIALIZATION_LIBRARY, SERIALIZATION_LIBRARY_DESC);
Expand Down Expand Up @@ -437,6 +443,15 @@ public void processOpts() {
additionalProperties.put(this.serializationLibrary.name(), true);
}

if (additionalProperties.containsKey(MAP_FILE_BINARY_TO_BYTE_ARRAY)) {
setMapFileBinaryToByteArray(convertPropertyToBooleanAndWriteBack(MAP_FILE_BINARY_TO_BYTE_ARRAY));
}
additionalProperties.put(MAP_FILE_BINARY_TO_BYTE_ARRAY, mapFileBinaryToByteArray);
if (mapFileBinaryToByteArray) {
typeMapping.put("file", "kotlin.ByteArray");
typeMapping.put("binary", "kotlin.ByteArray");
}

if (additionalProperties.containsKey(GENERATE_ONEOF_ANYOF_WRAPPERS)) {
setGenerateOneOfAnyOfWrappers(Boolean.parseBoolean(additionalProperties.get(GENERATE_ONEOF_ANYOF_WRAPPERS).toString()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ import com.squareup.moshi.adapter
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -100,6 +115,7 @@ import com.squareup.moshi.adapter

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -71,6 +86,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -73,6 +88,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
}

/**
* Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
*
* @param byteArray The given file
* @return The guessed Content-Type
*/
protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
val contentType = try {
URLConnection.guessContentTypeFromStream(byteArray.inputStream())
} catch (io: IOException) {
"application/octet-stream"
}
return contentType
}

/**
* Guess Content-Type header from the given file (defaults to "application/octet-stream").
*
Expand All @@ -74,6 +89,7 @@ open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClie

protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when {
content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType ->
MultipartBody.Builder()
Expand Down
Loading

0 comments on commit 462f450

Please sign in to comment.