Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.octopusden.octopus.dms.service.impl.ComponentServiceImpl.kt Maven / Gradle / Ivy
package org.octopusden.octopus.dms.service.impl
import org.octopusden.octopus.dms.client.common.dto.ArtifactFullDTO
import org.octopusden.octopus.dms.client.common.dto.ArtifactType
import org.octopusden.octopus.dms.client.common.dto.ArtifactsDTO
import org.octopusden.octopus.dms.client.common.dto.BuildStatus
import org.octopusden.octopus.dms.client.common.dto.ComponentDTO
import org.octopusden.octopus.dms.client.common.dto.ComponentRequestFilter
import org.octopusden.octopus.dms.client.common.dto.DependencyDTO
import org.octopusden.octopus.dms.client.common.dto.RegisterArtifactDTO
import org.octopusden.octopus.dms.dto.ComponentVersionStatusWithInfoDTO
import org.octopusden.octopus.dms.dto.DownloadArtifactDTO
import org.octopusden.octopus.dms.entity.Component
import org.octopusden.octopus.dms.entity.ComponentVersion
import org.octopusden.octopus.dms.entity.ComponentVersionArtifact
import org.octopusden.octopus.dms.event.DeleteComponentVersionArtifactEvent
import org.octopusden.octopus.dms.event.RegisterComponentVersionArtifactEvent
import org.octopusden.octopus.dms.exception.ArtifactAlreadyExistsException
import org.octopusden.octopus.dms.exception.NotFoundException
import org.octopusden.octopus.dms.exception.VersionFormatIsNotValidException
import org.octopusden.octopus.dms.repository.ArtifactRepository
import org.octopusden.octopus.dms.repository.ComponentRepository
import org.octopusden.octopus.dms.repository.ComponentVersionArtifactRepository
import org.octopusden.octopus.dms.repository.ComponentVersionRepository
import org.octopusden.octopus.dms.service.ComponentService
import org.octopusden.octopus.dms.service.ComponentsRegistryService
import org.octopusden.octopus.dms.service.ReleaseManagementService
import org.octopusden.octopus.dms.service.StorageService
import org.octopusden.octopus.releasemanagementservice.client.ReleaseManagementServiceClient
import org.octopusden.releng.versions.NumericVersionFactory
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
@Service
class ComponentServiceImpl(
private val componentsRegistryService: ComponentsRegistryService,
private val releaseManagementService: ReleaseManagementService,
private val storageService: StorageService,
private val componentRepository: ComponentRepository,
private val componentVersionRepository: ComponentVersionRepository,
private val componentVersionArtifactRepository: ComponentVersionArtifactRepository,
private val artifactRepository: ArtifactRepository,
private val applicationEventPublisher: ApplicationEventPublisher,
private val releaseManagementServiceClient: ReleaseManagementServiceClient
) : ComponentService {
override fun getComponents(filter: ComponentRequestFilter?): List {
log.info("Get components")
return componentsRegistryService.getExternalComponents(filter).sortedWith { a, b ->
a.name.lowercase().compareTo(b.name.lowercase())
}
}
override fun getDependencies(componentName: String, version: String): List {
log.info("Get dependencies of '$componentName:$version'")
return componentVersionRepository.findByComponentNameAndVersion(componentName, version)
?.let { componentVersion ->
val components = componentsRegistryService.getExternalComponents(null).associateBy { c -> c.id }
return releaseManagementServiceClient.getBuild(
componentVersion.component.name,
componentVersion.version
).dependencies.mapNotNull { (component, version, _) ->
componentVersionRepository.findByComponentNameAndVersion(component, version)
}.map { cv ->
DependencyDTO(components[cv.component.name]!!, cv.version, BuildStatus.UNKNOWN_STATUS)
}.sortedWith { a, b ->
a.component.name.lowercase().compareTo(b.component.name.lowercase()).takeIf { it != 0 }
?: a.version.compareTo(b.version)
}
} ?: throw NotFoundException("Version '$version' is not found for component '$componentName'")
}
@Transactional(readOnly = false)
override fun deleteComponent(componentName: String, dryRun: Boolean) {
log.info("Delete component '$componentName'")
componentRepository.findByName(componentName)?.let { component ->
if (!dryRun) {
componentVersionRepository.findByComponent(component).forEach { componentVersion ->
componentVersionArtifactRepository.findByComponentVersion(componentVersion).forEach {
applicationEventPublisher.publishEvent(
DeleteComponentVersionArtifactEvent(
componentName, componentVersion.version, it.toFullDTO()
)
)
}
}
componentRepository.delete(component)
}
log.info("$component deleted")
}
}
@Transactional(readOnly = true)
override fun getComponentMinorVersions(componentName: String): Set {
log.info("Get minor versions of component '$componentName'")
componentsRegistryService.checkComponent(componentName)
return componentVersionRepository.getMinorVersionsByComponentName(componentName)
}
@Transactional(readOnly = true)
override fun getComponentVersions(
componentName: String, minorVersions: List, includeRc: Boolean
): List {
log.info("Get versions of component '$componentName'")
componentsRegistryService.checkComponent(componentName)
val componentVersionEntities = if (minorVersions.isEmpty()) {
componentVersionRepository.findByComponentName(componentName)
} else {
componentVersionRepository.findByComponentNameAndMinorVersions(componentName, minorVersions)
}
val allowedStatuses = if (includeRc) {
arrayOf(BuildStatus.RELEASE, BuildStatus.RC)
} else {
arrayOf(BuildStatus.RELEASE)
}
val numericVersionFactory = NumericVersionFactory(componentsRegistryService.getVersionNames())
return if (componentVersionEntities.isEmpty()) {
emptyList()
} else {
val componentBuilds = releaseManagementService.getComponentBuilds(
componentName, allowedStatuses, componentVersionEntities.map { it.version }.toSet()
).associateBy { build -> build.version }
componentVersionEntities.map { cv ->
ComponentVersionStatusWithInfoDTO(
cv.component.name,
cv.version,
componentBuilds[cv.version]?.status ?: BuildStatus.UNKNOWN_STATUS,
numericVersionFactory.create(cv.version)
)
}.filter {
allowedStatuses.contains(it.status)
}
}
}
@Transactional(readOnly = false)
override fun deleteComponentVersion(componentName: String, version: String, dryRun: Boolean) {
log.info("Delete version '$version' of component '$componentName'")
val componentVersion = componentVersionRepository.findByComponentNameAndVersion(componentName, version)
?: with(normalizeComponentVersion(componentName, version)) {
componentVersionRepository.findByComponentNameAndVersion(componentName, this.second)
}
componentVersion?.let {
if (!dryRun) {
componentVersionArtifactRepository.findByComponentVersion(it).forEach { componentVersionArtifact ->
applicationEventPublisher.publishEvent(
DeleteComponentVersionArtifactEvent(
componentName, it.version, componentVersionArtifact.toFullDTO()
)
)
}
componentVersionRepository.delete(it)
}
log.info("$it deleted")
}
}
@Transactional(readOnly = true)
override fun getPreviousLinesLatestVersions(
componentName: String,
version: String,
includeRc: Boolean
): List {
log.info("Get previous versions for version '$version' of component '$componentName'" + if (includeRc) " including RC" else "")
componentsRegistryService.checkComponent(componentName)
val (_, buildVersion) = normalizeComponentVersion(componentName, version)
releaseManagementService.getComponentBuild(componentName, buildVersion, null)
val versions = componentVersionRepository.findByComponentName(componentName).map { it.version }.toSet()
val allowedStatuses = if (includeRc) {
arrayOf(BuildStatus.RELEASE, BuildStatus.RC)
} else {
arrayOf(BuildStatus.RELEASE)
}
val builds = releaseManagementService.getComponentBuilds(componentName, allowedStatuses, versions)
return componentsRegistryService.findPreviousLines(componentName, version, builds.map { it.version })
}
@Transactional(readOnly = true)
override fun getComponentVersionArtifacts(
componentName: String,
version: String,
type: ArtifactType?
): ArtifactsDTO {
log.info("Get artifacts" + (type?.let { " with type '$it'" } ?: "") + " for version '$version' of component '$componentName'")
componentsRegistryService.checkComponent(componentName)
val (_, buildVersion) = normalizeComponentVersion(componentName, version)
val build = releaseManagementService.getComponentBuild(componentName, buildVersion, type)
return ArtifactsDTO(
build,
if (type == null) {
componentVersionArtifactRepository.findByComponentVersionComponentNameAndComponentVersionVersion(
componentName,
buildVersion
)
} else {
componentVersionArtifactRepository.findByComponentVersionComponentNameAndComponentVersionVersionAndType(
componentName,
buildVersion,
type
)
}.map { it.toShortDTO() } //TODO: filter distribution artifacts if version status is RC?
)
}
@Transactional(readOnly = true)
override fun getComponentVersionArtifact(
componentName: String, version: String, artifactId: Long
): ArtifactFullDTO {
log.info("Get artifact with ID '$artifactId' for version '$version' of component '$componentName'")
componentsRegistryService.checkComponent(componentName)
val (_, buildVersion) = normalizeComponentVersion(componentName, version)
return getOrElseThrow(componentName, buildVersion, artifactId).toFullDTO().also {
releaseManagementService.getComponentBuild(componentName, buildVersion, it.type)
}
}
@Transactional(readOnly = true)
override fun downloadComponentVersionArtifact(
componentName: String, version: String, artifactId: Long
): DownloadArtifactDTO {
log.info("Download artifact with ID '$artifactId' for version '$version' of component '$componentName'")
componentsRegistryService.checkComponent(componentName)
val (_, buildVersion) = normalizeComponentVersion(componentName, version)
val componentVersionArtifactEntity = getOrElseThrow(componentName, buildVersion, artifactId)
releaseManagementService.getComponentBuild(componentName, buildVersion, componentVersionArtifactEntity.type)
return DownloadArtifactDTO(
componentVersionArtifactEntity.artifact.fileName,
storageService.download(componentVersionArtifactEntity.artifact, false)
)
}
@Transactional(readOnly = false)
override fun registerComponentVersionArtifact(
componentName: String,
version: String,
artifactId: Long,
failOnAlreadyExists: Boolean,
registerArtifactDTO: RegisterArtifactDTO
): ArtifactFullDTO {
log.info("Register '${registerArtifactDTO.type}' artifact with ID '$artifactId' for version '$version' of component '$componentName'")
componentsRegistryService.checkComponent(componentName)
val (minorVersion, buildVersion) = normalizeComponentVersion(componentName, version)
releaseManagementService.getComponentBuild(componentName, buildVersion, registerArtifactDTO.type)
val artifact = artifactRepository.findById(artifactId).orElseThrow {
NotFoundException("Artifact with ID '$artifactId' is not found")
}
storageService.find(artifact, false)
componentRepository.lock(componentName.hashCode()) // prevent race condition inserting component/version/artifact
val component = componentRepository.findByName(componentName)
?: componentRepository.save(Component(name = componentName))
val componentVersion = componentVersionRepository.findByComponentAndVersion(component, buildVersion)
?: componentVersionRepository.save(
ComponentVersion(
component = component,
minorVersion = minorVersion,
version = buildVersion
)
)
val componentVersionArtifact =
componentVersionArtifactRepository.findByComponentVersionAndArtifact(componentVersion, artifact)?.let {
with("Artifact with ID '$artifactId' is already registered for version '$buildVersion' of component '$componentName'") {
if (failOnAlreadyExists) {
throw ArtifactAlreadyExistsException(this)
}
log.info(this)
}
it
} ?: componentVersionArtifactRepository.save(
ComponentVersionArtifact(
componentVersion = componentVersion,
artifact = artifact,
type = registerArtifactDTO.type
)
)
return componentVersionArtifact.toFullDTO().also {
applicationEventPublisher.publishEvent(
RegisterComponentVersionArtifactEvent(componentName, buildVersion, it)
)
}
}
@Transactional(readOnly = false)
override fun deleteComponentVersionArtifact(
componentName: String,
version: String,
artifactId: Long,
dryRun: Boolean
) {
log.info("Delete artifact with ID '$artifactId' for version '$version' of component '$componentName'")
val (_, buildVersion) = normalizeComponentVersion(componentName, version)
componentVersionArtifactRepository.findByComponentVersionComponentNameAndComponentVersionVersionAndArtifactId(
componentName, buildVersion, artifactId
)?.let {
if (!dryRun) {
applicationEventPublisher.publishEvent(
DeleteComponentVersionArtifactEvent(componentName, buildVersion, it.toFullDTO())
)
componentVersionArtifactRepository.delete(it)
}
log.info("$it deleted")
}
}
private fun getOrElseThrow(componentName: String, version: String, artifactId: Long) =
componentVersionArtifactRepository.findByComponentVersionComponentNameAndComponentVersionVersionAndArtifactId(
componentName, version, artifactId
) ?: throw NotFoundException("Artifact with ID '$artifactId' is not found for version '$version' of component '$componentName'")
private fun normalizeComponentVersion(componentName: String, version: String): Pair {
val detailedComponentVersion = componentsRegistryService.getDetailedComponentVersion(componentName, version)
return detailedComponentVersion.minorVersion.version to (when (version) {
detailedComponentVersion.buildVersion.version -> version
detailedComponentVersion.releaseVersion.version -> {
try {
releaseManagementService.getComponentBuild(componentName, version)
.takeIf { build -> build.status in normalizeStatuses }
?.let { build ->
val buildVersion = build.version
log.info("Release version '$version' of component '$componentName' is normalized to build version '$buildVersion'")
buildVersion
}
} catch (e: org.octopusden.octopus.releasemanagementservice.client.common.exception.NotFoundException) {
null
} ?: throw NotFoundException("Unable to normalize version '$version' of component '$componentName'")
}
else -> {
throw VersionFormatIsNotValidException("Version '$version' of component '$componentName' does not fit RELEASE or BUILD format")
}
})
}
companion object {
private val normalizeStatuses = arrayOf(BuildStatus.RC, BuildStatus.RELEASE)
private val log = LoggerFactory.getLogger(ComponentServiceImpl::class.java)
}
}