From 21401825f3b7e8bd010cc1e498f3265360fe3c56 Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 25 Feb 2024 21:28:07 +0700 Subject: [PATCH 01/11] add custom protocol support --- .../artifact/metadata/MetadataLoader.scala | 44 ++++++++----------- .../sbt/metadata/MetadataLoaderGroup.scala | 2 +- .../sbt/service/VersionServiceImpl.scala | 4 +- version.sbt | 2 +- 4 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala b/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala index e912c80..56f6429 100644 --- a/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala +++ b/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala @@ -8,6 +8,9 @@ import org.jmotor.sbt.artifact.exception.ArtifactNotFoundException import java.net.URL import java.nio.file.{Files, Path, Paths} import scala.concurrent.{ExecutionContext, Future, Promise} +import scala.io.Source +import java.io.ByteArrayInputStream +import java.net.HttpURLConnection /** * Component: Description: Date: 2018/2/8 @@ -23,33 +26,24 @@ trait MetadataLoader { attrs: Map[String, String] = Map.empty ): Future[Seq[ArtifactVersion]] - def download(organization: String, artifactId: String, url: String)(implicit ec: ExecutionContext): Future[Path] = { - val src = new URL(url) - val dispatcher = URLHandlerRegistry.getDefault + def download(organization: String, artifactId: String, url: String)(implicit ec: ExecutionContext): Future[Path] = Future { - dispatcher.getURLInfo(src) - }.flatMap { - case info if info.isReachable => - val promise = Promise[Path] - val path = Files.createTempFile(s"maven-metadata-$organization-$artifactId", ".xml") - try { - dispatcher.download( - src, - path.toFile, - new CopyProgressListener { - override def start(evt: CopyProgressEvent): Unit = {} - - override def progress(evt: CopyProgressEvent): Unit = {} + try { + val src = new URL(url) + val connection = src.openConnection() - override def end(evt: CopyProgressEvent): Unit = - promise.success(path) - } - ) - } catch { - case e: Throwable => promise.failure(e) + Option(connection.getInputStream()).map { is => + val path = Files.createTempFile(s"maven-metadata-$organization-$artifactId", ".xml") + // might better write via file output stream + Files.write(path, is.readAllBytes()) + path } - promise.future - case _ => throw ArtifactNotFoundException(organization, artifactId) + } catch { + case e: java.io.FileNotFoundException => None + case e: Throwable => throw e + } + }.flatMap { + case None => Future.failed(ArtifactNotFoundException(organization, artifactId)) + case Some(path) => Future.successful(path) } - } } diff --git a/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala b/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala index b4a25e1..7e9bde7 100644 --- a/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala +++ b/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala @@ -54,7 +54,7 @@ class MetadataLoaderGroup(scalaVersion: String, scalaBinaryVersion: String, load sbtSettings: Option[(String, String)] ): (String, Map[String, String]) = { val remapVersion = module.crossVersion match { - case _: Disabled => None + case _: Disabled => sbtSettings.map { case (sbt, scala) => s"${scala}_$sbt" } case binary: Binary => Option(binary.prefix + scalaBinaryVersion) case _: Full => Option(scalaVersion) case _: Patch => Option(scalaVersion) diff --git a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala index 454b788..2138dad 100644 --- a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala +++ b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala @@ -84,7 +84,7 @@ class VersionServiceImpl(logger: Logger, scalaVersion: String, scalaBinaryVersio val loaders: Seq[MetadataLoader] = resolvers.map { case repo: MavenRepository => val url = repo.root - if (isRemote(url)) { + if (isRemote(url) && scala.util.Try(new java.net.URL(url)).isSuccess) { Option(new MavenRepoMetadataLoader(url)) } else { None @@ -106,6 +106,6 @@ class VersionServiceImpl(logger: Logger, scalaVersion: String, scalaBinaryVersio } private[this] def isRemote(url: String): Boolean = - url.startsWith("http://") || url.startsWith("https://") + !url.startsWith("file://") && !url.startsWith("jar://") } diff --git a/version.sbt b/version.sbt index b15e398..1ef27f2 100644 --- a/version.sbt +++ b/version.sbt @@ -1,3 +1,3 @@ -ThisBuild / version := "1.2.8" +ThisBuild / version := "1.2.9-SNAPSHOT" ThisBuild / versionScheme := Some("semver-spec") From 979dc71bd70a6ca7453fdb90556afe55255d89a8 Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 25 Feb 2024 21:45:39 +0700 Subject: [PATCH 02/11] update version test --- src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala b/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala index d03a0b2..26d3f27 100644 --- a/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala +++ b/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala @@ -37,7 +37,7 @@ class VersionServiceSpec extends AnyFunSuite { val versionService = VersionService(Logger.Null, "2.12.4", "2.12", resolvers, Seq.empty) val future = versionService.checkPluginForUpdates( - ModuleID("org.jetbrains", "sbt-idea-shell", "2017.2"), + ModuleID("ch.epfl.scala", "sbt-bloop", "1.5.13"), "1.0", "2.12" ) From f23316318af53ea2a436e456da1d3367412d5fdd Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Mon, 26 Feb 2024 14:54:36 +0700 Subject: [PATCH 03/11] add error log on invalid maven url --- .../scala/org/jmotor/sbt/service/VersionServiceImpl.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala index 2138dad..9ea0716 100644 --- a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala +++ b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala @@ -18,6 +18,7 @@ import sbt.util.Logger import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.control.NonFatal +import scala.util.{Failure, Success} /** * Component: Description: Date: 2018/2/9 @@ -84,8 +85,11 @@ class VersionServiceImpl(logger: Logger, scalaVersion: String, scalaBinaryVersio val loaders: Seq[MetadataLoader] = resolvers.map { case repo: MavenRepository => val url = repo.root - if (isRemote(url) && scala.util.Try(new java.net.URL(url)).isSuccess) { - Option(new MavenRepoMetadataLoader(url)) + if (isRemote(url)) { + scala.util.Try(new java.net.URL(url)) match { + case Failure(e) => logger.err(s"""Invalid URL "$url" for Maven repository: ${e.getMessage}"""); None + case Success(_) => Option(new MavenRepoMetadataLoader(url)) + } } else { None } From 143b29b3e5a48837e255807ba0f4061e7501208b Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 10 Mar 2024 12:56:01 +0700 Subject: [PATCH 04/11] use output stream on download --- .../artifact/metadata/MetadataLoader.scala | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala b/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala index 56f6429..e45b14c 100644 --- a/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala +++ b/src/main/scala/org/jmotor/sbt/artifact/metadata/MetadataLoader.scala @@ -5,12 +5,13 @@ import org.apache.ivy.util.{CopyProgressEvent, CopyProgressListener} import org.apache.maven.artifact.versioning.ArtifactVersion import org.jmotor.sbt.artifact.exception.ArtifactNotFoundException -import java.net.URL +import java.net.{URL, URI} import java.nio.file.{Files, Path, Paths} import scala.concurrent.{ExecutionContext, Future, Promise} import scala.io.Source import java.io.ByteArrayInputStream import java.net.HttpURLConnection +import java.io.FileOutputStream /** * Component: Description: Date: 2018/2/8 @@ -29,14 +30,25 @@ trait MetadataLoader { def download(organization: String, artifactId: String, url: String)(implicit ec: ExecutionContext): Future[Path] = Future { try { - val src = new URL(url) + val src = new URI(url).toURL() val connection = src.openConnection() Option(connection.getInputStream()).map { is => val path = Files.createTempFile(s"maven-metadata-$organization-$artifactId", ".xml") - // might better write via file output stream - Files.write(path, is.readAllBytes()) - path + val os = new FileOutputStream(path.toAbsolutePath.toString()) + + try { + val buffer = new Array[Byte](8192) + var bytesRead = is.read(buffer) + while (bytesRead >= 0) { + os.write(buffer, 0, bytesRead) + bytesRead = is.read(buffer) + } + path + } finally { + is.close() + os.close() + } } } catch { case e: java.io.FileNotFoundException => None From a7870c3500b2c14d0f15b4d8ea7a921b975757d6 Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 10 Mar 2024 13:15:10 +0700 Subject: [PATCH 05/11] revert sbt plugin metadata loader update --- .../scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala | 2 +- src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala b/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala index 7e9bde7..b4a25e1 100644 --- a/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala +++ b/src/main/scala/org/jmotor/sbt/metadata/MetadataLoaderGroup.scala @@ -54,7 +54,7 @@ class MetadataLoaderGroup(scalaVersion: String, scalaBinaryVersion: String, load sbtSettings: Option[(String, String)] ): (String, Map[String, String]) = { val remapVersion = module.crossVersion match { - case _: Disabled => sbtSettings.map { case (sbt, scala) => s"${scala}_$sbt" } + case _: Disabled => None case binary: Binary => Option(binary.prefix + scalaBinaryVersion) case _: Full => Option(scalaVersion) case _: Patch => Option(scalaVersion) diff --git a/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala b/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala index 26d3f27..d03a0b2 100644 --- a/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala +++ b/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala @@ -37,7 +37,7 @@ class VersionServiceSpec extends AnyFunSuite { val versionService = VersionService(Logger.Null, "2.12.4", "2.12", resolvers, Seq.empty) val future = versionService.checkPluginForUpdates( - ModuleID("ch.epfl.scala", "sbt-bloop", "1.5.13"), + ModuleID("org.jetbrains", "sbt-idea-shell", "2017.2"), "1.0", "2.12" ) From 415b752dffc77ec469424a5ca71eee1d70f97421 Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 10 Mar 2024 13:15:54 +0700 Subject: [PATCH 06/11] update isremote check --- .../org/jmotor/sbt/service/VersionServiceImpl.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala index 9ea0716..00538c9 100644 --- a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala +++ b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala @@ -27,17 +27,17 @@ import scala.util.{Failure, Success} * AI */ class VersionServiceImpl(logger: Logger, scalaVersion: String, scalaBinaryVersion: String, resolvers: Seq[Resolver]) - extends VersionService { + extends VersionService { private[this] lazy val groups = getLoaderGroups(resolvers) override def checkForUpdates(module: ModuleID): Future[ModuleStatus] = check(module) override def checkPluginForUpdates( - module: ModuleID, - sbtBinaryVersion: String, - sbtScalaBinaryVersion: String - ): Future[ModuleStatus] = + module: ModuleID, + sbtBinaryVersion: String, + sbtScalaBinaryVersion: String + ): Future[ModuleStatus] = check(module, Option(sbtBinaryVersion -> sbtScalaBinaryVersion)) private[this] def check(module: ModuleID, sbtSettings: Option[(String, String)] = None): Future[ModuleStatus] = { @@ -110,6 +110,6 @@ class VersionServiceImpl(logger: Logger, scalaVersion: String, scalaBinaryVersio } private[this] def isRemote(url: String): Boolean = - !url.startsWith("file://") && !url.startsWith("jar://") + !url.startsWith("file:") && !url.startsWith("jar:") } From c52130803580aa35793d79a1c76db697b6dcd898 Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 10 Mar 2024 13:16:10 +0700 Subject: [PATCH 07/11] fix url issue on windows --- .../metadata/loader/MavenRepoMetadataLoader.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala b/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala index 4709073..7b0456a 100644 --- a/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala +++ b/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala @@ -4,7 +4,7 @@ import org.apache.maven.artifact.versioning.{ArtifactVersion, DefaultArtifactVer import org.jmotor.sbt.artifact.exception.ArtifactNotFoundException import org.jmotor.sbt.artifact.metadata.MetadataLoader -import java.net.URL +import java.net.URI import java.nio.file.{Files, Paths} import scala.concurrent.{ExecutionContext, Future} import scala.xml.XML @@ -18,8 +18,8 @@ import scala.xml.XML class MavenRepoMetadataLoader(url: String)(implicit ec: ExecutionContext) extends MetadataLoader { private[this] lazy val (protocol, base) = { - val u = new URL(url) - u.getProtocol + "://" -> url.replace(s"${u.getProtocol}://", "") + val u = new URI(url) + (u.getScheme -> u.getHost) } override def getVersions( @@ -28,7 +28,7 @@ class MavenRepoMetadataLoader(url: String)(implicit ec: ExecutionContext) extend attrs: Map[String, String] ): Future[Seq[ArtifactVersion]] = { val location = - protocol + Paths.get(base, organization.split('.').mkString("/"), artifactId, "maven-metadata.xml").toString + protocol + s"$base/${organization.split('.').mkString("/")}/$artifactId/maven-metadata.xml" download(organization, artifactId, location).map { file => val stream = Files.newInputStream(file) try { From ea601c06dd7057787de44f90ff2ee56c228c386b Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 10 Mar 2024 13:16:40 +0700 Subject: [PATCH 08/11] update .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 33c6b38..60cfdd3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ lib_managed/ src_managed/ project/boot/ project/plugins/project/ +project/metals.sbt +project/project # Scala-IDE specific .scala_dependencies @@ -18,3 +20,6 @@ project/plugins/project/ .idea .bsp +.bloop +.metals +.vscode \ No newline at end of file From 8c1529c396b146e405cd2d1fe2567e55332cdf49 Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 10 Mar 2024 13:29:26 +0700 Subject: [PATCH 09/11] fix deprecated URL constructor warning on jdk >= 20 --- .../sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala | 2 +- src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala b/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala index 7b0456a..46f4d2e 100644 --- a/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala +++ b/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala @@ -19,7 +19,7 @@ class MavenRepoMetadataLoader(url: String)(implicit ec: ExecutionContext) extend private[this] lazy val (protocol, base) = { val u = new URI(url) - (u.getScheme -> u.getHost) + (u.getScheme + "://" -> u.getRawSchemeSpecificPart.stripPrefix("//")) } override def getVersions( diff --git a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala index 00538c9..d93f17c 100644 --- a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala +++ b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala @@ -86,7 +86,7 @@ class VersionServiceImpl(logger: Logger, scalaVersion: String, scalaBinaryVersio case repo: MavenRepository => val url = repo.root if (isRemote(url)) { - scala.util.Try(new java.net.URL(url)) match { + scala.util.Try(new java.net.URI(url).toURL()) match { case Failure(e) => logger.err(s"""Invalid URL "$url" for Maven repository: ${e.getMessage}"""); None case Success(_) => Option(new MavenRepoMetadataLoader(url)) } From 10148c2f5ebdeb42067eef25acfd8b15429c8aa0 Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Sun, 10 Mar 2024 13:38:14 +0700 Subject: [PATCH 10/11] remove whitespace changes --- .../org/jmotor/sbt/service/VersionServiceImpl.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala index d93f17c..f29e440 100644 --- a/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala +++ b/src/main/scala/org/jmotor/sbt/service/VersionServiceImpl.scala @@ -27,17 +27,17 @@ import scala.util.{Failure, Success} * AI */ class VersionServiceImpl(logger: Logger, scalaVersion: String, scalaBinaryVersion: String, resolvers: Seq[Resolver]) - extends VersionService { + extends VersionService { private[this] lazy val groups = getLoaderGroups(resolvers) override def checkForUpdates(module: ModuleID): Future[ModuleStatus] = check(module) override def checkPluginForUpdates( - module: ModuleID, - sbtBinaryVersion: String, - sbtScalaBinaryVersion: String - ): Future[ModuleStatus] = + module: ModuleID, + sbtBinaryVersion: String, + sbtScalaBinaryVersion: String + ): Future[ModuleStatus] = check(module, Option(sbtBinaryVersion -> sbtScalaBinaryVersion)) private[this] def check(module: ModuleID, sbtSettings: Option[(String, String)] = None): Future[ModuleStatus] = { From 95542897861b9a3e3d6f1f4a917fca18f29be01e Mon Sep 17 00:00:00 2001 From: Roman Langolf Date: Mon, 11 Mar 2024 11:53:46 +0700 Subject: [PATCH 11/11] add custom protocol hadler test --- build.sbt | 3 +- .../loader/MavenRepoMetadataLoader.scala | 5 +-- .../sbt/service/VersionServiceSpec.scala | 31 +++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 3521ed8..4717da5 100644 --- a/build.sbt +++ b/build.sbt @@ -16,7 +16,8 @@ inThisBuild(List( "yanbo.ai@gmail.com", url("https://aiyanbo.github.io/") ) - ) + ), + Test / fork := true )) coverageScalacPluginVersion := "2.0.10" diff --git a/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala b/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala index 46f4d2e..b802172 100644 --- a/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala +++ b/src/main/scala/org/jmotor/sbt/artifact/metadata/loader/MavenRepoMetadataLoader.scala @@ -27,8 +27,9 @@ class MavenRepoMetadataLoader(url: String)(implicit ec: ExecutionContext) extend artifactId: String, attrs: Map[String, String] ): Future[Seq[ArtifactVersion]] = { - val location = - protocol + s"$base/${organization.split('.').mkString("/")}/$artifactId/maven-metadata.xml" + val location = new URI(s"$protocol$base/${organization.split('.').mkString("/")}/$artifactId/maven-metadata.xml") + .normalize() + .toString() download(organization, artifactId, location).map { file => val stream = Files.newInputStream(file) try { diff --git a/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala b/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala index d03a0b2..cdd7b45 100644 --- a/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala +++ b/src/test/scala/org/jmotor/sbt/service/VersionServiceSpec.scala @@ -7,6 +7,8 @@ import sbt.util.Logger import scala.concurrent.Await import scala.concurrent.duration.* +import java.net.{URI, URL, URLConnection, URLStreamHandler, URLStreamHandlerFactory} +import java.util.concurrent.atomic.AtomicReference /** Component: Description: Date: 2018/3/1 * @@ -57,4 +59,33 @@ class VersionServiceSpec extends AnyFunSuite { assert(status.status == Status.Expired) } + test("uses custom protocol handlers") { + val downloadsCalled = new AtomicReference(Vector.empty[String]) + + // setting stream handler can be executed only once on jvm + // to be able to execute it multiple times from sbt shell it requires forking enabled like "Test / fork := true" + URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory { + def createURLStreamHandler(protocol: String): URLStreamHandler = protocol match { + case "artifactregistry" => + new URLStreamHandler { + protected def openConnection(url: URL): URLConnection = { + downloadsCalled.getAndUpdate(_ :+ url.toString()) + new URI(s"https://${url.getHost}${url.getPath()}").normalize.toURL.openConnection + } + } + case _ => null + } + }) + + val testResolver = MavenRepo("m2", "artifactregistry://repo1.maven.org/maven2/") + val versionService = VersionService(Logger.Null, "2.12.4", "2.12", Seq(testResolver), Seq.empty) + Await.result(versionService.checkForUpdates(ModuleID("com.google.guava", "guava", "23.0-jre")), 30.seconds) + + assert( + downloadsCalled + .get() + .contains("artifactregistry://repo1.maven.org/maven2/com/google/guava/guava/maven-metadata.xml") + ) + } + }