diff --git a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt index e788056925e..afc11aa4bf8 100644 --- a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt +++ b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/impl/ivy.kt @@ -17,32 +17,33 @@ import org.apache.ivy.plugins.resolver.ChainResolver import org.apache.ivy.plugins.resolver.URLResolver import org.apache.ivy.util.DefaultMessageLogger import org.apache.ivy.util.Message -import org.jetbrains.kotlin.script.util.DependsOn import org.jetbrains.kotlin.script.util.KotlinAnnotatedScriptDependenciesResolver -import org.jetbrains.kotlin.script.util.Repository import org.jetbrains.kotlin.script.util.resolvers.DirectResolver -import org.jetbrains.kotlin.script.util.resolvers.Resolver +import org.jetbrains.kotlin.script.util.resolvers.experimental.GenericArtifactCoordinates +import org.jetbrains.kotlin.script.util.resolvers.experimental.GenericRepositoryCoordinates +import org.jetbrains.kotlin.script.util.resolvers.experimental.GenericRepositoryWithBridge +import org.jetbrains.kotlin.script.util.resolvers.experimental.MavenArtifactCoordinates import java.io.File import java.net.MalformedURLException import java.net.URL -class IvyResolver : Resolver { +class IvyResolver : GenericRepositoryWithBridge { - private fun String.isValidParam() = isNotBlank() + private fun String?.isValidParam() = this?.isNotBlank() ?: false - override fun tryResolve(dependsOn: DependsOn): Iterable? { - val artifactId = when { - dependsOn.groupId.isValidParam() || dependsOn.artifactId.isValidParam() -> { - listOf(dependsOn.groupId, dependsOn.artifactId, dependsOn.version) + override fun tryResolve(artifactCoordinates: GenericArtifactCoordinates): Iterable? = with (artifactCoordinates) { + val artifactId = + if (this is MavenArtifactCoordinates && (groupId.isValidParam() || artifactId.isValidParam())) { + listOf(groupId.orEmpty(), artifactId.orEmpty(), version.orEmpty()) + } else { + val stringCoordinates = string + if (stringCoordinates.isValidParam() && stringCoordinates.count { it == ':' } == 2) { + stringCoordinates.split(':') + } else { + error("Unknown set of arguments to maven resolver: $stringCoordinates") + } } - dependsOn.value.isValidParam() && dependsOn.value.count { it == ':' } == 2 -> { - dependsOn.value.split(':') - } - else -> { - error("Unknown set of arguments to maven resolver: ${dependsOn.value}") - } - } - return resolveArtifact(artifactId) + resolveArtifact(artifactId) } private val ivyResolvers = arrayListOf() @@ -101,17 +102,19 @@ class IvyResolver : Resolver { return report.allArtifactsReports.map { it.localFile } } - override fun tryAddRepo(annotation: Repository): Boolean { - val urlStr = annotation.url.takeIf { it.isValidParam() } ?: annotation.value.takeIf { it.isValidParam() } ?: return false - val url = urlStr.toRepositoryUrlOrNull() ?: return false - ivyResolvers.add( - URLResolver().apply { - isM2compatible = true - name = annotation.id.takeIf { it.isValidParam() } ?: url.host - addArtifactPattern("${url.toString().let { if (it.endsWith('/')) it else "$it/" }}$DEFAULT_ARTIFACT_PATTERN") - } - ) - return true + override fun tryAddRepository(repositoryCoordinates: GenericRepositoryCoordinates): Boolean { + val url = repositoryCoordinates.url + if (url != null) { + ivyResolvers.add( + URLResolver().apply { + isM2compatible = true + name = repositoryCoordinates.name.takeIf { it.isValidParam() } ?: url.host + addArtifactPattern("${url.toString().let { if (it.endsWith('/')) it else "$it/" }}$DEFAULT_ARTIFACT_PATTERN") + } + ) + return true + } + return false } companion object { @@ -123,12 +126,5 @@ class IvyResolver : Resolver { } } -private fun String.toRepositoryUrlOrNull(): URL? = - try { - URL(this) - } catch (_: MalformedURLException) { - null - } - class FilesAndIvyResolver : KotlinAnnotatedScriptDependenciesResolver(emptyList(), arrayListOf(DirectResolver(), IvyResolver()).asIterable()) diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/basic.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/basic.kt index 8e120ccd229..b892a0338d3 100644 --- a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/basic.kt +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/basic.kt @@ -16,25 +16,21 @@ package org.jetbrains.kotlin.script.util.resolvers -import org.jetbrains.kotlin.script.util.DependsOn import org.jetbrains.kotlin.script.util.Repository +import org.jetbrains.kotlin.script.util.resolvers.experimental.* import java.io.File import java.net.MalformedURLException import java.net.URL -interface Resolver { - fun tryResolve(dependsOn: DependsOn): Iterable? - fun tryAddRepo(annotation: Repository): Boolean +class DirectResolver : GenericRepositoryWithBridge { + override fun tryResolve(artifactCoordinates: GenericArtifactCoordinates): Iterable? = + artifactCoordinates.string.takeUnless(String::isBlank) + ?.let(::File)?.takeIf { it.exists() && (it.isFile || it.isDirectory) }?.let { listOf(it) } + + override fun tryAddRepository(repositoryCoordinates: GenericRepositoryCoordinates): Boolean = false } -class DirectResolver : Resolver { - override fun tryResolve(dependsOn: DependsOn): Iterable? = - dependsOn.value.takeUnless(String::isBlank)?.let(::File)?.takeIf { it.exists() && (it.isFile || it.isDirectory) }?.let { listOf(it) } - - override fun tryAddRepo(annotation: Repository): Boolean = false -} - -class FlatLibDirectoryResolver(vararg paths: File) : Resolver { +class FlatLibDirectoryResolver(vararg paths: File) : GenericRepositoryWithBridge { private val localRepos = arrayListOf() @@ -45,10 +41,10 @@ class FlatLibDirectoryResolver(vararg paths: File) : Resolver { localRepos.addAll(paths) } - override fun tryResolve(dependsOn: DependsOn): Iterable? { + override fun tryResolve(artifactCoordinates: GenericArtifactCoordinates): Iterable? { for (path in localRepos) { // TODO: add coordinates and wildcard matching - val res = dependsOn.value.takeUnless(String::isBlank) + val res = artifactCoordinates.string.takeUnless(String::isBlank) ?.let { File(path, it) } ?.takeIf { it.exists() && (it.isFile || it.isDirectory) } if (res != null) return listOf(res) @@ -56,18 +52,21 @@ class FlatLibDirectoryResolver(vararg paths: File) : Resolver { return null } - override fun tryAddRepo(annotation: Repository): Boolean { - val urlStr = annotation.url.takeIf { it.isNotBlank() } ?: annotation.value.takeIf { it.isNotBlank() } ?: return false - val dirFromUrl = urlStr.toRepositoryUrlOrNull()?.takeIf { it.protocol == "file" }?.path - val repoDir = (dirFromUrl ?: urlStr).toRepositoryFileOrNull() ?: return false + override fun tryAddRepository(repositoryCoordinates: GenericRepositoryCoordinates): Boolean { + val repoDir = repositoryCoordinates.file ?: return false localRepos.add(repoDir) return true } companion object { - fun tryCreate(annotation: Repository): FlatLibDirectoryResolver? = - annotation.value.takeUnless(String::isBlank)?.let(::File)?.takeIf { it.exists() && it.isDirectory } - ?.let { FlatLibDirectoryResolver(it) } + fun tryCreate(annotation: Repository): FlatLibDirectoryResolver? = tryCreate( + BasicRepositoryCoordinates( + annotation.url.takeUnless(String::isBlank) ?: annotation.value, annotation.id.takeUnless(String::isBlank) + ) + ) + + fun tryCreate(repositoryCoordinates: GenericRepositoryCoordinates): FlatLibDirectoryResolver? = + repositoryCoordinates.file?.let { FlatLibDirectoryResolver(it) } } } diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/experimental/genericResolver.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/experimental/genericResolver.kt new file mode 100644 index 00000000000..0cbaea867db --- /dev/null +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/experimental/genericResolver.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.script.util.resolvers.experimental + +import org.jetbrains.kotlin.script.util.DependsOn +import org.jetbrains.kotlin.script.util.Repository +import org.jetbrains.kotlin.script.util.resolvers.Resolver +import org.jetbrains.kotlin.script.util.resolvers.toRepositoryFileOrNull +import org.jetbrains.kotlin.script.util.resolvers.toRepositoryUrlOrNull +import java.io.File +import java.net.URL + +interface GenericArtifactCoordinates { + val string: String +} + +interface GenericRepositoryCoordinates { + val string: String + val name: String? get() = null + val url: URL? get() = string.toRepositoryUrlOrNull() + val file: File? get() = (url?.takeIf { it.protocol == "file" }?.path ?: string).toRepositoryFileOrNull() +} + +interface GenericResolver { + fun tryResolve(artifactCoordinates: GenericArtifactCoordinates): Iterable? + fun tryAddRepository(repositoryCoordinates: GenericRepositoryCoordinates): Boolean + + fun tryResolve(artifactCoordinates: String): Iterable? = tryResolve(BasicArtifactCoordinates(artifactCoordinates)) + + fun tryAddRepository(repositoryCoordinates: String, id: String? = null): Boolean = + tryAddRepository(BasicRepositoryCoordinates(repositoryCoordinates, id)) +} + +open class BasicArtifactCoordinates(override val string: String) : GenericArtifactCoordinates + +open class BasicRepositoryCoordinates(override val string: String, override val name: String? = null) : GenericRepositoryCoordinates + +interface GenericRepositoryWithBridge : GenericResolver, Resolver { + override fun tryResolve(dependsOn: DependsOn): Iterable? = + tryResolve( + with(dependsOn) { + MavenArtifactCoordinates(value, groupId, artifactId, version) + } + ) + + override fun tryAddRepo(annotation: Repository): Boolean = + with(annotation) { + tryAddRepository( + value.takeIf { it.isNotBlank() } ?: url, + id.takeIf { it.isNotBlank() } + ) + } +} + +open class MavenArtifactCoordinates( + val value: String?, + val groupId: String?, + val artifactId: String?, + val version: String? +) : GenericArtifactCoordinates { + override val string: String + get() = value.takeIf { it?.isNotBlank() ?: false } + ?: listOf(groupId, artifactId, version).filter { it?.isNotBlank() ?: false }.joinToString(":") +} diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/maven.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/maven.kt index 4bf280df620..1ddc3a8267b 100644 --- a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/maven.kt +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/maven.kt @@ -20,7 +20,10 @@ package org.jetbrains.kotlin.script.util.resolvers import com.jcabi.aether.Aether import org.jetbrains.kotlin.script.util.DependsOn -import org.jetbrains.kotlin.script.util.Repository +import org.jetbrains.kotlin.script.util.resolvers.experimental.GenericArtifactCoordinates +import org.jetbrains.kotlin.script.util.resolvers.experimental.GenericRepositoryCoordinates +import org.jetbrains.kotlin.script.util.resolvers.experimental.GenericRepositoryWithBridge +import org.jetbrains.kotlin.script.util.resolvers.experimental.MavenArtifactCoordinates import org.sonatype.aether.repository.RemoteRepository import org.sonatype.aether.resolution.DependencyResolutionException import org.sonatype.aether.util.artifact.DefaultArtifact @@ -30,7 +33,7 @@ import java.util.* val mavenCentral = RemoteRepository("maven-central", "default", "https://repo.maven.apache.org/maven2/") -class MavenResolver(val reportError: ((String) -> Unit)? = null): Resolver { +class MavenResolver(val reportError: ((String) -> Unit)? = null): GenericRepositoryWithBridge { // TODO: make robust val localRepo = File(File(System.getProperty("user.home")!!, ".m2"), "repository") @@ -39,9 +42,9 @@ class MavenResolver(val reportError: ((String) -> Unit)? = null): Resolver { private fun currentRepos() = if (repos.isEmpty()) arrayListOf(mavenCentral) else repos - private fun String.isValidParam() = isNotBlank() + private fun String?.isValidParam() = this?.isNotBlank() ?: false - override fun tryResolve(dependsOn: DependsOn): Iterable? { + override fun tryResolve(artifactCoordinates: GenericArtifactCoordinates): Iterable? { fun error(msg: String) { reportError?.invoke(msg) ?: throw RuntimeException(msg) @@ -49,16 +52,22 @@ class MavenResolver(val reportError: ((String) -> Unit)? = null): Resolver { fun String?.orNullIfBlank(): String? = this?.takeUnless(String::isBlank) - val artifactId: DefaultArtifact = when { - dependsOn.groupId.isValidParam() || dependsOn.artifactId.isValidParam() -> { - DefaultArtifact(dependsOn.groupId.orNullIfBlank(), dependsOn.artifactId.orNullIfBlank(), null, dependsOn.version.orNullIfBlank()) - } - dependsOn.value.isValidParam() && dependsOn.value.count { it == ':' } == 2 -> { - DefaultArtifact(dependsOn.value) - } - else -> { - error("Unknown set of arguments to maven resolver: ${dependsOn.value}") - return null + val artifactId: DefaultArtifact = with(artifactCoordinates) { + if (this is MavenArtifactCoordinates && (groupId.isValidParam() || artifactId.isValidParam())) { + DefaultArtifact( + groupId.orNullIfBlank(), + artifactId.orNullIfBlank(), + null, + version.orNullIfBlank() + ) + } else { + val coordinatesString = string + if (coordinatesString.isValidParam() && coordinatesString.count { it == ':' } == 2) { + DefaultArtifact(coordinatesString) + } else { + error("Unknown set of arguments to maven resolver: $coordinatesString") + return null + } } } @@ -69,22 +78,24 @@ class MavenResolver(val reportError: ((String) -> Unit)? = null): Resolver { else { error("resolving ${artifactId.artifactId} failed: no results") } - } - catch (e: DependencyResolutionException) { + } catch (e: DependencyResolutionException) { reportError?.invoke("resolving ${artifactId.artifactId} failed: $e") ?: throw e } return null } - override fun tryAddRepo(annotation: Repository): Boolean { - val urlStr = annotation.url.takeIf { it.isValidParam() } ?: annotation.value.takeIf { it.isValidParam() } ?: return false - urlStr.toRepositoryUrlOrNull() ?: return false - repos.add( + override fun tryAddRepository(repositoryCoordinates: GenericRepositoryCoordinates): Boolean { + val url = repositoryCoordinates.url + if (url != null) { + repos.add( RemoteRepository( - if (annotation.id.isValidParam()) annotation.id else "central", - "default", - urlStr - )) - return true + if (repositoryCoordinates.name.isValidParam()) repositoryCoordinates.name else url.host, + "default", + url.toString() + ) + ) + return true + } + return false } } diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/resolverInterface.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/resolverInterface.kt new file mode 100644 index 00000000000..aca41d58045 --- /dev/null +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolvers/resolverInterface.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.script.util.resolvers + +import org.jetbrains.kotlin.script.util.DependsOn +import org.jetbrains.kotlin.script.util.Repository +import java.io.File + +interface Resolver { + fun tryResolve(dependsOn: DependsOn): Iterable? + fun tryAddRepo(annotation: Repository): Boolean +} \ No newline at end of file