diff --git a/src/backend/common/common-artifact/artifact-api/build.gradle.kts b/src/backend/common/common-artifact/artifact-api/build.gradle.kts index aea671c46c..0b48cf042e 100644 --- a/src/backend/common/common-artifact/artifact-api/build.gradle.kts +++ b/src/backend/common/common-artifact/artifact-api/build.gradle.kts @@ -33,4 +33,5 @@ dependencies { api(project(":common:common-api")) api("com.tencent.devops:devops-boot-starter-plugin") compileOnly("com.google.guava:guava") + implementation("org.apache.commons:commons-lang3") } diff --git a/src/backend/common/common-artifact/artifact-api/src/main/kotlin/com/tencent/bkrepo/common/artifact/api/ArtifactInfo.kt b/src/backend/common/common-artifact/artifact-api/src/main/kotlin/com/tencent/bkrepo/common/artifact/api/ArtifactInfo.kt index 5b04cd6592..aa74b54130 100644 --- a/src/backend/common/common-artifact/artifact-api/src/main/kotlin/com/tencent/bkrepo/common/artifact/api/ArtifactInfo.kt +++ b/src/backend/common/common-artifact/artifact-api/src/main/kotlin/com/tencent/bkrepo/common/artifact/api/ArtifactInfo.kt @@ -34,6 +34,9 @@ package com.tencent.bkrepo.common.artifact.api import com.tencent.bkrepo.common.api.constant.CharPool.AT import com.tencent.bkrepo.common.api.constant.CharPool.SLASH import com.tencent.bkrepo.common.artifact.path.PathUtils +import org.apache.commons.lang3.reflect.FieldUtils +import java.lang.reflect.Modifier +import kotlin.reflect.full.primaryConstructor /** * 构件信息 @@ -131,4 +134,27 @@ open class ArtifactInfo( getArtifactVersion()?.let { builder.append(AT).append(it) } return builder.toString() } + + /** + * 根据当前对象的属性值以及传入的[projectId]和[repoName]构造新的实例 + */ + fun copy(projectId: String? = null, repoName: String? = null): ArtifactInfo { + val constructor = this::class.primaryConstructor!! + val paramMap = constructor.parameters.associateWith { param -> + when (param.name) { + ArtifactInfo::projectId.name -> projectId ?: this.projectId + ArtifactInfo::repoName.name -> repoName ?: this.repoName + else -> FieldUtils.readField(this, param.name, true) + } + } + val newInstance = constructor.callBy(paramMap) + val fields = FieldUtils.getAllFieldsList(this::class.java) + fields.forEach { + if (it.name != this::projectId.name && it.name != this::repoName.name && !Modifier.isStatic(it.modifiers)) { + val value = FieldUtils.readField(it, this, true) + FieldUtils.writeField(it, newInstance, value, true) + } + } + return newInstance + } } diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactContext.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactContext.kt index 7b1e7ad9a6..da5b5e41dc 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactContext.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactContext.kt @@ -46,6 +46,7 @@ import com.tencent.bkrepo.common.storage.credentials.StorageCredentials import com.tencent.bkrepo.repository.pojo.repo.RepositoryDetail import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse +import kotlin.reflect.full.primaryConstructor /** * 构件上下文 @@ -70,6 +71,7 @@ open class ArtifactContext( /** * 使用当前实例的属性,拷贝出一个新的[ArtifactContext]实例 * 传入的[repositoryDetail]会替换当前实例的仓库信息 + * 适用于CompositeRepository */ fun copy(repositoryDetail: RepositoryDetail): ArtifactContext { val context = this.javaClass.newInstance() @@ -78,6 +80,22 @@ open class ArtifactContext( return context } + /** + * 使用传入的[repositoryDetail]构造新的[ArtifactContext]实例 + * [instantiation]: 实例化方法, 为null时使用主构造函数 + * 适用于VirtualRepository: projectId, repoName, storageCredentials均会复制到新的实例, 并构造新的artifactInfo + */ + open fun copy( + repositoryDetail: RepositoryDetail, + instantiation: ((ArtifactInfo) -> ArtifactContext)? + ): ArtifactContext { + val artifactInfo = this.artifactInfo.copy(repositoryDetail.projectId, repositoryDetail.name) + val context = instantiation?.invoke(artifactInfo) + ?: this::class.primaryConstructor!!.call(repositoryDetail, artifactInfo) + context.contextAttributes = this.contextAttributes + return context + } + /** * 获取context Attributes map */ diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactDownloadContext.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactDownloadContext.kt index ea5aed7e25..03620dd6b2 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactDownloadContext.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactDownloadContext.kt @@ -41,6 +41,7 @@ import com.tencent.bkrepo.common.security.util.SecurityUtils import com.tencent.bkrepo.repository.pojo.node.NodeDetail import com.tencent.bkrepo.repository.pojo.packages.PackageVersion import com.tencent.bkrepo.repository.pojo.repo.RepositoryDetail +import kotlin.reflect.full.primaryConstructor /** * 构件下载context @@ -57,6 +58,17 @@ open class ArtifactDownloadContext( val artifacts = artifacts var shareUserId: String = StringPool.EMPTY + override fun copy( + repositoryDetail: RepositoryDetail, + instantiation: ((ArtifactInfo) -> ArtifactContext)? + ): ArtifactContext { + return super.copy(repositoryDetail) { artifactInfo -> + this::class.primaryConstructor!!.call( + repositoryDetail, artifactInfo, artifacts, this.userId, useDisposition + ) + } + } + @Suppress("UNCHECKED_CAST") fun getInterceptors(): List> { return DownloadInterceptorFactory.buildInterceptors(repo.configuration.settings) diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactQueryContext.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactQueryContext.kt index 5ad2334a73..e581333fa8 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactQueryContext.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactQueryContext.kt @@ -39,5 +39,5 @@ import com.tencent.bkrepo.repository.pojo.repo.RepositoryDetail */ open class ArtifactQueryContext( repo: RepositoryDetail? = null, - artifact: ArtifactInfo? = null, + artifact: ArtifactInfo? = null ) : ArtifactContext(repo, artifact) diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactRemoveContext.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactRemoveContext.kt index d066560c42..38481b92b0 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactRemoveContext.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactRemoveContext.kt @@ -31,7 +31,13 @@ package com.tencent.bkrepo.common.artifact.repository.context +import com.tencent.bkrepo.common.artifact.api.ArtifactInfo +import com.tencent.bkrepo.repository.pojo.repo.RepositoryDetail + /** * 构件删除context */ -open class ArtifactRemoveContext : ArtifactContext() +open class ArtifactRemoveContext( + repo: RepositoryDetail? = null, + artifact: ArtifactInfo? = null +) : ArtifactContext(repo, artifact) diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactSearchContext.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactSearchContext.kt index 44c98d38c1..9617b242a1 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactSearchContext.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactSearchContext.kt @@ -39,5 +39,5 @@ import com.tencent.bkrepo.repository.pojo.repo.RepositoryDetail */ open class ArtifactSearchContext( repo: RepositoryDetail? = null, - artifact: ArtifactInfo? = null, + artifact: ArtifactInfo? = null ) : ArtifactContext(repo, artifact) diff --git a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactUploadContext.kt b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactUploadContext.kt index 58cb8f1608..1e0f38c33f 100644 --- a/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactUploadContext.kt +++ b/src/backend/common/common-artifact/artifact-service/src/main/kotlin/com/tencent/bkrepo/common/artifact/repository/context/ArtifactUploadContext.kt @@ -68,6 +68,35 @@ open class ArtifactUploadContext : ArtifactContext { this.artifactFileMap = artifactFileMap } + constructor( + repo: RepositoryDetail, + artifactFileMap: ArtifactFileMap, + artifactInfo: ArtifactInfo? = null + ) : super(repo, artifactInfo) { + this.artifactFileMap = artifactFileMap + } + + override fun copy( + repositoryDetail: RepositoryDetail, + instantiation: ((ArtifactInfo) -> ArtifactContext)? + ): ArtifactContext { + return super.copy(repositoryDetail) { artifactInfo -> + if (artifactFile != null) { + javaClass.getConstructor( + RepositoryDetail::class.java, + ArtifactFile::class.java, + ArtifactInfo::class.java + ).newInstance(repositoryDetail, artifactFile, artifactInfo) + } else { + javaClass.getConstructor( + RepositoryDetail::class.java, + ArtifactFileMap::class.java, + ArtifactInfo::class.java + ).newInstance(repositoryDetail, artifactFileMap, artifactInfo) + } + } + } + /** * 根据[name]获取构件文件[ArtifactFile] *