All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jetbrains.pluginverifier.misc.RestApis.kt Maven / Gradle / Ivy

package com.jetbrains.pluginverifier.misc

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.type.CollectionType
import com.fasterxml.jackson.databind.type.TypeFactory
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.jetbrains.pluginverifier.network.threadFactory
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream
import org.bouncycastle.cms.CMSSignedData
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.time.Duration
import java.util.concurrent.Executors

fun createHttpClient(timeout: Duration = Duration.ofMinutes(5)): HttpClient {
  return HttpClient.newBuilder().connectTimeout(timeout)
          .executor(Executors.newCachedThreadPool(
            threadFactory("plugin-verifier-http-%d", daemon = true)
          ))
          .followRedirects(HttpClient.Redirect.NORMAL)
          .build()
}

class RestApis {
  private val httpClient = createHttpClient()
  private val jackson = jacksonObjectMapper()
          .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

  fun getRawString(url: String, timeout: Duration = Duration.ofMinutes(5)): RestApiResult {
    val request = get(url, timeout)

    val response = httpClient.send(request, HttpResponse.BodyHandlers.ofString())
    if (response.statusCode() != 200) {
      return RestApiFailed(response.body(), response.statusCode())
    }
    return RestApiOk(response.body())
  }

  fun  get(url: String, payloadType: Class, timeout: Duration = Duration.ofMinutes(5)): RestApiResult {
    val request = get(url, timeout)

    val response = httpClient.send(request, HttpResponse.BodyHandlers.ofString())
    if (response.statusCode() != 200) {
      return RestApiFailed(response.body(), response.statusCode())
    }
    val responseJson = response.body()
    val payloadObject = jackson.readValue(responseJson, payloadType)
    return RestApiOk(payloadObject)
  }


  fun  getList(url: String, elementClass: Class, timeout: Duration = Duration.ofMinutes(5)): RestApiResult> {
    val request = get(url, timeout)

    val response = httpClient.send(request, HttpResponse.BodyHandlers.ofString())
    if (response.statusCode() != 200) {
      return RestApiFailed(response.body(), response.statusCode())
    }
    val responseString = response.body()
    val listTypeToken = TypeFactory.defaultInstance().constructCollectionType(List::class.java, elementClass)
    val list: List  = jackson.readValue(responseString, listTypeToken)
    return RestApiOk(list)
  }

  fun  getSigned(url: String, type: Class, timeout: Duration = Duration.ofMinutes(5)): RestApiResult {
    val payloadBytes = when (val byteResult = getBytes(url, timeout)) {
      is RestApiOk -> byteResult.payload
      is RestApiFailed -> return RestApiFailed(byteResult, byteResult.statusCode)
    }
    val signedContent = CMSSignedData(payloadBytes).signedContent.content as ByteArray
    val result = jackson.readValue(XZCompressorInputStream(signedContent.inputStream()).reader(), type)
    return RestApiOk(result)
  }

  fun  getSignedList(url: String, elementClass: Class, timeout: Duration = Duration.ofMinutes(5)): RestApiResult> {
    val payloadBytes = when (val byteResult = getBytes(url, timeout)) {
      is RestApiOk -> byteResult.payload
      is RestApiFailed -> return RestApiFailed(byteResult, byteResult.statusCode)
    }
    val signedContent = CMSSignedData(payloadBytes).signedContent.content as ByteArray
    val list: List = jackson.readValue(XZCompressorInputStream(signedContent.inputStream()).reader(), getTypeTokenForList(elementClass))
    return RestApiOk(list)
  }

  fun getBytes(url: String, timeout: Duration = Duration.ofMinutes(5)): RestApiResult {
    val httpGet = get(url, timeout)

    val response = httpClient.send(httpGet, HttpResponse.BodyHandlers.ofByteArray())
    if (response.statusCode() != 200) {
      return RestApiFailed(response.body(), response.statusCode())
    }
    return RestApiOk(response.body())
  }

  private fun get(url: String, timeout: Duration): HttpRequest = HttpRequest.newBuilder().GET()
          .uri(URI.create(url))
          .timeout(timeout)
          .build()

  private fun  getTypeTokenForList(elementClass: Class): CollectionType =
          TypeFactory.defaultInstance().constructCollectionType(List::class.java, elementClass)
}

sealed class RestApiResult
data class RestApiOk(val payload: T) : RestApiResult()
data class RestApiFailed(val errorPayload: Any, val statusCode: Int) : RestApiResult()




© 2015 - 2025 Weber Informatics LLC | Privacy Policy