Rewrite new scripting maven resolver directly to eclipse aether
This commit is contained in:
@@ -9,11 +9,20 @@ jvmTarget = "1.6"
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile(kotlinStdlib())
|
compile(kotlinStdlib())
|
||||||
compile(project(":kotlin-scripting-dependencies"))
|
compile(project(":kotlin-scripting-dependencies"))
|
||||||
compile("org.jetbrains.kotlin:jcabi-aether:1.0-dev-3")
|
compile("org.eclipse.aether:aether-api:1.1.0")
|
||||||
compile("org.sonatype.aether:aether-api:1.13.1")
|
compile("org.eclipse.aether:aether-impl:1.1.0")
|
||||||
testCompile("org.apache.maven:maven-settings-builder:3.0.5")
|
compile("org.eclipse.aether:aether-util:1.1.0")
|
||||||
|
compile("org.eclipse.aether:aether-connector-basic:1.1.0")
|
||||||
|
compile("org.eclipse.aether:aether-transport-wagon:1.1.0")
|
||||||
|
compile("org.eclipse.aether:aether-transport-http:1.1.0")
|
||||||
|
compile("org.eclipse.aether:aether-transport-file:1.1.0")
|
||||||
|
compile("org.apache.maven:maven-core:3.6.3")
|
||||||
|
compile("org.apache.maven:maven-settings-builder:3.6.3")
|
||||||
|
compile("org.apache.maven:maven-aether-provider:3.3.9")
|
||||||
|
compile("org.apache.maven.wagon:wagon-provider-api:3.3.4")
|
||||||
testCompile(projectTests(":kotlin-scripting-dependencies"))
|
testCompile(projectTests(":kotlin-scripting-dependencies"))
|
||||||
testCompile(commonDep("junit"))
|
testCompile(commonDep("junit"))
|
||||||
|
testRuntimeOnly("org.slf4j:slf4j-nop:1.7.30")
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
+21
-13
@@ -5,12 +5,11 @@
|
|||||||
|
|
||||||
package kotlin.script.experimental.dependencies.maven
|
package kotlin.script.experimental.dependencies.maven
|
||||||
|
|
||||||
import com.jcabi.aether.Aether
|
import org.eclipse.aether.artifact.DefaultArtifact
|
||||||
import org.sonatype.aether.repository.Authentication
|
import org.eclipse.aether.repository.RemoteRepository
|
||||||
import org.sonatype.aether.repository.RemoteRepository
|
import org.eclipse.aether.resolution.DependencyResolutionException
|
||||||
import org.sonatype.aether.resolution.DependencyResolutionException
|
import org.eclipse.aether.util.artifact.JavaScopes
|
||||||
import org.sonatype.aether.util.artifact.DefaultArtifact
|
import org.eclipse.aether.util.repository.AuthenticationBuilder
|
||||||
import org.sonatype.aether.util.artifact.JavaScopes
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
@@ -18,8 +17,9 @@ import kotlin.script.experimental.dependencies.ExternalDependenciesResolver
|
|||||||
import kotlin.script.experimental.dependencies.RepositoryCoordinates
|
import kotlin.script.experimental.dependencies.RepositoryCoordinates
|
||||||
import kotlin.script.experimental.dependencies.impl.makeResolveFailureResult
|
import kotlin.script.experimental.dependencies.impl.makeResolveFailureResult
|
||||||
import kotlin.script.experimental.dependencies.impl.toRepositoryUrlOrNull
|
import kotlin.script.experimental.dependencies.impl.toRepositoryUrlOrNull
|
||||||
|
import kotlin.script.experimental.dependencies.maven.impl.AetherResolveSession
|
||||||
|
import kotlin.script.experimental.dependencies.maven.impl.mavenCentral
|
||||||
|
|
||||||
val mavenCentral = RemoteRepository("maven-central", "default", "https://repo.maven.apache.org/maven2/")
|
|
||||||
|
|
||||||
class MavenRepositoryCoordinates(
|
class MavenRepositoryCoordinates(
|
||||||
url: String,
|
url: String,
|
||||||
@@ -45,7 +45,7 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
|
|||||||
|
|
||||||
private fun remoteRepositories() = if (repos.isEmpty()) arrayListOf(mavenCentral) else repos
|
private fun remoteRepositories() = if (repos.isEmpty()) arrayListOf(mavenCentral) else repos
|
||||||
|
|
||||||
private fun allRepositories() = remoteRepositories().map { it.url!!.toString() } + localRepo.toString()
|
private fun allRepositories() = remoteRepositories() + localRepo
|
||||||
|
|
||||||
private fun String.toMavenArtifact(): DefaultArtifact? =
|
private fun String.toMavenArtifact(): DefaultArtifact? =
|
||||||
if (this.isNotBlank() && this.count { it == ':' } == 2) DefaultArtifact(this)
|
if (this.isNotBlank() && this.count { it == ':' } == 2) DefaultArtifact(this)
|
||||||
@@ -56,11 +56,11 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
|
|||||||
val artifactId = artifactCoordinates.toMavenArtifact()!!
|
val artifactId = artifactCoordinates.toMavenArtifact()!!
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val deps = Aether(remoteRepositories(), localRepo).resolve(artifactId, JavaScopes.RUNTIME)
|
val deps = AetherResolveSession(localRepo, remoteRepositories()).resolve(artifactId, JavaScopes.RUNTIME)
|
||||||
if (deps != null)
|
if (deps != null)
|
||||||
return ResultWithDiagnostics.Success(deps.map { it.file })
|
return ResultWithDiagnostics.Success(deps.map { it.file })
|
||||||
} catch (e: DependencyResolutionException) {
|
} catch (e: DependencyResolutionException) {
|
||||||
|
return makeResolveFailureResult(e.message ?: "unknown error")
|
||||||
}
|
}
|
||||||
return makeResolveFailureResult(allRepositories().map { "$it: $artifactId not found" })
|
return makeResolveFailureResult(allRepositories().map { "$it: $artifactId not found" })
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
|
|||||||
override fun addRepository(repositoryCoordinates: RepositoryCoordinates) {
|
override fun addRepository(repositoryCoordinates: RepositoryCoordinates) {
|
||||||
val url = repositoryCoordinates.toRepositoryUrlOrNull()
|
val url = repositoryCoordinates.toRepositoryUrlOrNull()
|
||||||
?: throw IllegalArgumentException("Invalid Maven repository URL: ${repositoryCoordinates}")
|
?: throw IllegalArgumentException("Invalid Maven repository URL: ${repositoryCoordinates}")
|
||||||
val repo = RemoteRepository(
|
val repo = RemoteRepository.Builder(
|
||||||
repositoryCoordinates.string,
|
repositoryCoordinates.string,
|
||||||
"default",
|
"default",
|
||||||
url.toString()
|
url.toString()
|
||||||
@@ -80,8 +80,16 @@ class MavenDependenciesResolver : ExternalDependenciesResolver {
|
|||||||
if (repositoryCoordinates is MavenRepositoryCoordinates) {
|
if (repositoryCoordinates is MavenRepositoryCoordinates) {
|
||||||
val username = repositoryCoordinates.username?.let(::tryResolveEnvironmentVariable)
|
val username = repositoryCoordinates.username?.let(::tryResolveEnvironmentVariable)
|
||||||
val password = repositoryCoordinates.password?.let(::tryResolveEnvironmentVariable)
|
val password = repositoryCoordinates.password?.let(::tryResolveEnvironmentVariable)
|
||||||
repo.authentication = Authentication(username, password, repositoryCoordinates.privateKeyFile, repositoryCoordinates.passPhrase)
|
if (username != null) {
|
||||||
|
val auth = AuthenticationBuilder().apply {
|
||||||
|
addUsername(username)
|
||||||
|
if (password != null) {
|
||||||
|
addPassword(password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repo.setAuthentication(auth.build())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
repos.add(repo)
|
repos.add(repo.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+227
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.dependencies.maven.impl
|
||||||
|
|
||||||
|
import org.apache.commons.io.filefilter.NameFileFilter
|
||||||
|
import org.apache.maven.repository.internal.MavenRepositorySystemUtils
|
||||||
|
import org.apache.maven.settings.Settings
|
||||||
|
import org.apache.maven.settings.SettingsUtils
|
||||||
|
import org.apache.maven.settings.TrackableBase
|
||||||
|
import org.apache.maven.settings.building.*
|
||||||
|
import org.eclipse.aether.RepositorySystem
|
||||||
|
import org.eclipse.aether.RepositorySystemSession
|
||||||
|
import org.eclipse.aether.artifact.Artifact
|
||||||
|
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.graph.DependencyFilter
|
||||||
|
import org.eclipse.aether.repository.LocalRepository
|
||||||
|
import org.eclipse.aether.repository.Proxy
|
||||||
|
import org.eclipse.aether.repository.RemoteRepository
|
||||||
|
import org.eclipse.aether.resolution.ArtifactResult
|
||||||
|
import org.eclipse.aether.resolution.DependencyRequest
|
||||||
|
import org.eclipse.aether.resolution.DependencyResolutionException
|
||||||
|
import org.eclipse.aether.resolution.DependencyResult
|
||||||
|
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 org.eclipse.aether.util.filter.DependencyFilterUtils
|
||||||
|
import org.eclipse.aether.util.repository.AuthenticationBuilder
|
||||||
|
import org.eclipse.aether.util.repository.DefaultMirrorSelector
|
||||||
|
import org.eclipse.aether.util.repository.DefaultProxySelector
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileFilter
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
val mavenCentral: RemoteRepository = RemoteRepository.Builder("maven central", "default", "https://repo.maven.apache.org/maven2/").build()
|
||||||
|
|
||||||
|
class AetherResolveSession(
|
||||||
|
val localRepo: File = File(File(System.getProperty("user.home")!!, ".m2"), "repository"),
|
||||||
|
remoteRepos: List<RemoteRepository> = listOf(mavenCentral)
|
||||||
|
) {
|
||||||
|
|
||||||
|
val remotes by lazy {
|
||||||
|
val proxySelector = settings.getActiveProxy()?.let { proxy ->
|
||||||
|
val selector = DefaultProxySelector()
|
||||||
|
val auth = with (AuthenticationBuilder()) {
|
||||||
|
addUsername(proxy.username)
|
||||||
|
addPassword(proxy.password)
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
selector.add(
|
||||||
|
Proxy(
|
||||||
|
proxy.protocol,
|
||||||
|
proxy.host,
|
||||||
|
proxy.port,
|
||||||
|
auth
|
||||||
|
), proxy.nonProxyHosts
|
||||||
|
)
|
||||||
|
selector
|
||||||
|
}
|
||||||
|
val mirrorSelector = getMirrorSelector()
|
||||||
|
remoteRepos.mapNotNull {
|
||||||
|
val builder = RemoteRepository.Builder(it)
|
||||||
|
if (proxySelector != null) {
|
||||||
|
builder.setProxy(proxySelector.getProxy(builder.build()))
|
||||||
|
}
|
||||||
|
val built = builder.build()
|
||||||
|
if (!built.protocol.matches(Regex("https?|file"))) {
|
||||||
|
//Logger.warn(
|
||||||
|
// this,
|
||||||
|
// "%s ignored (only S3, HTTP/S, and FILE are supported)",
|
||||||
|
// repo
|
||||||
|
//);
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
mirrorSelector.getMirror(built) ?: built
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val repositorySystem: RepositorySystem by lazy {
|
||||||
|
val locator = MavenRepositorySystemUtils.newServiceLocator()
|
||||||
|
locator.addService(
|
||||||
|
RepositoryConnectorFactory::class.java,
|
||||||
|
BasicRepositoryConnectorFactory::class.java
|
||||||
|
)
|
||||||
|
locator.addService(
|
||||||
|
TransporterFactory::class.java,
|
||||||
|
FileTransporterFactory::class.java
|
||||||
|
)
|
||||||
|
locator.addService(
|
||||||
|
TransporterFactory::class.java,
|
||||||
|
HttpTransporterFactory::class.java
|
||||||
|
)
|
||||||
|
locator.getService(RepositorySystem::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val repositorySystemSession: RepositorySystemSession by lazy {
|
||||||
|
val localRepo = LocalRepository(localRepo.absolutePath)
|
||||||
|
MavenRepositorySystemUtils.newSession().also {
|
||||||
|
it.localRepositoryManager = repositorySystem.newLocalRepositoryManager(it, localRepo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resolve(coordinates: String, scope: String, filter: DependencyFilter? = null): List<Artifact>? =
|
||||||
|
resolve(DefaultArtifact(coordinates), scope, filter)
|
||||||
|
|
||||||
|
fun resolve(root: Artifact, scope: String, filter: DependencyFilter? = null): List<Artifact>? {
|
||||||
|
|
||||||
|
return fetch(
|
||||||
|
repositorySystem,
|
||||||
|
repositorySystemSession,
|
||||||
|
DependencyRequest(
|
||||||
|
request(Dependency(root, scope)),
|
||||||
|
filter ?: DependencyFilterUtils.classpathFilter(scope)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun request(root: Dependency): CollectRequest? {
|
||||||
|
val request = CollectRequest()
|
||||||
|
request.root = root
|
||||||
|
for (repo in remotes) {
|
||||||
|
request.addRepository(repo)
|
||||||
|
}
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetch(system: RepositorySystem, session: RepositorySystemSession, dreq: DependencyRequest): List<Artifact>? {
|
||||||
|
val deps: MutableList<Artifact> = LinkedList()
|
||||||
|
try {
|
||||||
|
var results: Collection<ArtifactResult>
|
||||||
|
synchronized(this) {
|
||||||
|
results = system.resolveDependencies(session, dreq)
|
||||||
|
.artifactResults
|
||||||
|
}
|
||||||
|
for (res in results) {
|
||||||
|
deps.add(res.artifact)
|
||||||
|
}
|
||||||
|
// @checkstyle IllegalCatch (1 line)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
throw DependencyResolutionException(
|
||||||
|
DependencyResult(dreq),
|
||||||
|
IllegalArgumentException( //Logger.format(
|
||||||
|
// "failed to load '%s' from %[list]s into %s",
|
||||||
|
// dreq.getCollectRequest().getRoot(),
|
||||||
|
// Aether.reps(dreq.getCollectRequest().getRepositories()),
|
||||||
|
// session.getLocalRepositoryManager()
|
||||||
|
// .getRepository()
|
||||||
|
// .getBasedir()
|
||||||
|
//),
|
||||||
|
ex
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return deps
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMirrorSelector(): DefaultMirrorSelector {
|
||||||
|
val selector = DefaultMirrorSelector()
|
||||||
|
val mirrors = settings.mirrors
|
||||||
|
if (mirrors != null) {
|
||||||
|
for (mirror in mirrors) {
|
||||||
|
selector.add(
|
||||||
|
mirror.id, mirror.url, mirror.layout, false,
|
||||||
|
mirror.mirrorOf, mirror.mirrorOfLayouts
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selector
|
||||||
|
}
|
||||||
|
|
||||||
|
private val settings: Settings by lazy {
|
||||||
|
val builder: SettingsBuilder = DefaultSettingsBuilderFactory().newInstance()
|
||||||
|
val request: SettingsBuildingRequest = DefaultSettingsBuildingRequest()
|
||||||
|
val user = System.getProperty("org.apache.maven.user-settings")
|
||||||
|
if (user == null) {
|
||||||
|
request.userSettingsFile = File(
|
||||||
|
File(System.getProperty("user.home")).absoluteFile,
|
||||||
|
"/.m2/settings.xml"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
request.userSettingsFile = File(user)
|
||||||
|
}
|
||||||
|
val global = System.getProperty("org.apache.maven.global-settings")
|
||||||
|
if (global != null) {
|
||||||
|
request.globalSettingsFile = File(global)
|
||||||
|
}
|
||||||
|
val result: SettingsBuildingResult
|
||||||
|
result = try {
|
||||||
|
builder.build(request)
|
||||||
|
} catch (ex: SettingsBuildingException) {
|
||||||
|
throw IllegalStateException(ex)
|
||||||
|
}
|
||||||
|
this.invokers(builder, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invokers(
|
||||||
|
builder: SettingsBuilder,
|
||||||
|
result: SettingsBuildingResult
|
||||||
|
): Settings {
|
||||||
|
var main = result.effectiveSettings
|
||||||
|
val files = File(System.getProperty("user.dir"))
|
||||||
|
.parentFile.listFiles(
|
||||||
|
NameFileFilter("interpolated-settings.xml") as FileFilter
|
||||||
|
)
|
||||||
|
if (files.size == 1) {
|
||||||
|
val irequest =
|
||||||
|
DefaultSettingsBuildingRequest()
|
||||||
|
irequest.userSettingsFile = files[0]
|
||||||
|
main = try {
|
||||||
|
val isettings = builder.build(irequest)
|
||||||
|
.effectiveSettings
|
||||||
|
SettingsUtils.merge(isettings, main, TrackableBase.USER_LEVEL)
|
||||||
|
isettings
|
||||||
|
} catch (ex: SettingsBuildingException) {
|
||||||
|
throw java.lang.IllegalStateException(ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return main
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user