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

com.jetbrains.pluginverifier.ide.IntelliJRepositoryIndexParser.kt Maven / Gradle / Ivy

/*
 * Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 */

package com.jetbrains.pluginverifier.ide

import com.jetbrains.plugin.structure.ide.IntelliJPlatformProduct
import com.jetbrains.plugin.structure.intellij.version.IdeVersion
import com.jetbrains.pluginverifier.ide.repositories.ArtifactJson
import com.jetbrains.pluginverifier.ide.repositories.IntelliJIdeRepository
import java.net.URL
import java.time.Instant
import java.time.ZoneOffset


/**
 * Utility class used to parse index of available IDEs from [IntelliJIdeRepository].
 */
internal class IntelliJRepositoryIndexParser {

  fun parseArtifacts(artifacts: List, channel: IntelliJIdeRepository.Channel): List {
    val allAvailableIdes = arrayListOf()

    /**
     * (group-id, version) is a unique key for grouping artifacts.
     */
    val groupedArtifacts = artifacts.groupBy { it.groupId to it.version }
    for ((groupAndVersion, artifactsOfVersion) in groupedArtifacts) {
      val (groupId, version) = groupAndVersion

      /**
       * Build number of this IDE is written in "BUILD".content artifact's key.
       */
      val buildNumber = artifactsOfVersion.find { it.artifactId == "BUILD" }?.content ?: continue

      val ideArtifacts = artifactsOfVersion.filter {
        it.packaging == "zip" && IntelliJIdeRepository.getProductCodeByArtifactId(it.artifactId) != null
      }

      for (artifactInfo in ideArtifacts) {
        val productCode = IntelliJIdeRepository.getProductCodeByArtifactId(artifactInfo.artifactId) ?: continue

        val ideVersion = IdeVersion.createIdeVersionIfValid(buildNumber)
          ?.setProductCodeIfAbsent(productCode)
          ?: continue

        val product = IntelliJPlatformProduct.fromIdeVersion(ideVersion) ?: continue

        val downloadUrl = buildDownloadUrl(artifactInfo, channel, groupId, version)

        val isRelease = channel == IntelliJIdeRepository.Channel.RELEASE && isReleaseLikeVersion(artifactInfo.version)
        val releasedVersion = version.takeIf { isRelease }
        val uploadDate = Instant.ofEpochMilli(artifactInfo.lastModifiedUnixTimeMs).atZone(ZoneOffset.UTC).toLocalDate()
        val availableIde = AvailableIde(ideVersion, releasedVersion, downloadUrl, uploadDate, product)
        allAvailableIdes.add(availableIde)
      }
    }

    /**
     * Remove duplicated IDEs.
     */
    return allAvailableIdes
      .groupBy { it.version }
      .mapValues { getUniqueIde(it.value) }
      .values.toList()
  }

  private fun buildDownloadUrl(
    artifactInfo: ArtifactJson,
    channel: IntelliJIdeRepository.Channel,
    groupId: String,
    version: String
  ) = with(artifactInfo) {
    URL(channel.repositoryUrl + "/${groupId.replace('.', '/')}/$artifactId/$version/$artifactId-$version.$packaging")
  }

  /**
   * From [ides], which is a list of IDEs with the same versions,
   * selects the most appropriate.
   *
   * For one [AvailableIde.version] there might be two [AvailableIde]s:
   * one with `isRelease = true` and another with `isRelease = false`.
   * We'd like to keep only the release one.
   */
  private fun getUniqueIde(ides: List): AvailableIde =
    if (ides.size == 2) {
      val first = ides.first()
      val second = ides.last()
      if (first.isRelease != second.isRelease) {
        if (first.isRelease) {
          first
        } else {
          second
        }
      } else {
        first
      }
    } else {
      ides.first()
    }

  /**
   * Examples of release versions:
   * - 2017.3
   * - 2016.2.4
   * - 15.0.2
   *
   * Note that IDEs prior to 2016 were numbered as ``13.*, 14.*, 15.*``
   * and IDEs as of 2016 are numbered as ``2016.*``, ``2017.*``, ...
   */
  private fun isReleaseLikeVersion(version: String): Boolean {
    val ideVersion = IdeVersion.createIdeVersionIfValid(version)
    return ideVersion != null && (ideVersion.baselineVersion <= 15 || ideVersion.baselineVersion >= 2016)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy