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

migratedb.v1.dependency_downloader.DependencyResolver.kt Maven / Gradle / Ivy

/*
 * Copyright 2022-2024 The MigrateDB contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package migratedb.v1.dependency_downloader

import org.apache.maven.repository.internal.*
import org.eclipse.aether.RepositorySystem
import org.eclipse.aether.RepositorySystemSession
import org.eclipse.aether.RequestTrace
import org.eclipse.aether.artifact.DefaultArtifact
import org.eclipse.aether.collection.CollectRequest
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory
import org.eclipse.aether.graph.Dependency
import org.eclipse.aether.impl.*
import org.eclipse.aether.repository.LocalRepository
import org.eclipse.aether.repository.RemoteRepository
import org.eclipse.aether.resolution.ArtifactResult
import org.eclipse.aether.resolution.DependencyRequest
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory
import org.eclipse.aether.spi.connector.transport.TransporterFactory
import org.eclipse.aether.transport.file.FileTransporterFactory
import org.eclipse.aether.transport.http.HttpTransporterFactory
import java.io.File

/**
 * Resolves Maven artifacts from remote repository, downloads into local repository.
 */
class DependencyResolver(
    private val localRepository: File,
    remoteRepositoryUrl: String,
    remoteRepositoryId: String
) : AutoCloseable {
    private val repositorySystem = newRepositorySystem()
    private val session = newSession()
    private val remoteRepository: RemoteRepository = RemoteRepository.Builder(
        remoteRepositoryId,
        "default",
        remoteRepositoryUrl
    ).build()

    @JvmName("resolveCoordinates")
    fun resolve(coordinates: Collection): List {
        return resolve(coordinates.map { Dependency(DefaultArtifact(it), null) })
    }

    fun resolve(dependencies: Collection): List {
        val result = DependencyResolutionResult()
        val depRequest = createDependencyRequest(dependencies)
        addToResult(result, repositorySystem.resolveDependencies(session, depRequest).artifactResults)
        if (result.unresolvedDependencies.isNotEmpty()) {
            throw IllegalStateException("Unresolved dependencies: ${result.unresolvedDependencies}")
        }
        if (result.resolutionErrors.isNotEmpty()) {
            throw IllegalStateException("Dependency resolution errors: ${result.resolutionErrors}")
        }
        return result.resolvedDependencies.toList()
    }

    private fun createDependencyRequest(dependencies: Collection): DependencyRequest {
        val collect = CollectRequest()
        collect.requestContext = "none"
        collect.dependencies = (dependencies as? List) ?: dependencies.toList()
        collect.addRepository(remoteRepository)
        val trace = RequestTrace.newChild(null, collect)
        val dependencyRequest = DependencyRequest(collect, null)
        dependencyRequest.trace = trace
        collect.trace = RequestTrace.newChild(trace, dependencyRequest)
        dependencyRequest.root = repositorySystem.collectDependencies(session, collect).root
        return dependencyRequest
    }

    private fun addToResult(result: DependencyResolutionResult, results: Collection) {
        for (artifactResult in results) {
            val node = artifactResult.request.dependencyNode
            if (artifactResult.isResolved) {
                result.resolvedDependencies.add(node.dependency)
            } else {
                result.resolutionErrors[node.dependency] = ArrayList(artifactResult.exceptions)
            }
        }
    }

    private fun newSession(): RepositorySystemSession {
        val session = MavenRepositorySystemUtils.newSession()
        val localRepo = LocalRepository(localRepository)
        session.localRepositoryManager = repositorySystem.newLocalRepositoryManager(session, localRepo)
        return session
    }

    private fun newRepositorySystem(): RepositorySystem {
        @Suppress("DEPRECATION") val locator = DefaultServiceLocator()
        locator.addService(ArtifactDescriptorReader::class.java, DefaultArtifactDescriptorReader::class.java)
        locator.addService(VersionResolver::class.java, DefaultVersionResolver::class.java)
        locator.addService(VersionRangeResolver::class.java, DefaultVersionRangeResolver::class.java)
        locator.addService(MetadataGeneratorFactory::class.java, SnapshotMetadataGeneratorFactory::class.java)
        locator.addService(MetadataGeneratorFactory::class.java, VersionsMetadataGeneratorFactory::class.java)
        locator.addService(ModelCacheFactory::class.java, DefaultModelCacheFactory::class.java)
        locator.addService(RepositoryConnectorFactory::class.java, BasicRepositoryConnectorFactory::class.java)
        locator.addService(TransporterFactory::class.java, FileTransporterFactory::class.java)
        locator.addService(TransporterFactory::class.java, HttpTransporterFactory::class.java)
        return locator.getService(RepositorySystem::class.java)
    }

    override fun close() {
        repositorySystem.shutdown()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy