Avoid the use of URL

**Problem**
`java.net.URL` calls out to the network to perform `equals`,
so we should remove that from anywhere that can be involved in caching etc.

**Solution**
This changes java.net.URL to java.net.URI in Keys.
This commit is contained in:
Eugene Yokota 2024-12-04 22:07:52 -05:00
parent 0075b2fd0e
commit 02c7cf309d
6 changed files with 37 additions and 42 deletions

View File

@ -8,6 +8,7 @@
package sbt
import java.io.File
import java.net.URI
import java.time.OffsetDateTime
import java.util.jar.{ Attributes, Manifest }
import scala.jdk.CollectionConverters.*
@ -196,7 +197,7 @@ object Pkg:
def addImplManifestAttributes(
name: String,
version: String,
homepage: Option[java.net.URL],
homepage: Option[URI],
org: String,
orgName: String
): PackageOption = {

View File

@ -9,7 +9,6 @@
package sbt
import java.io.{ File, PrintWriter }
import java.net.URL
import java.nio.file.{ Files, Paths, Path => NioPath }
import java.util.Optional
import java.util.concurrent.TimeUnit
@ -2060,8 +2059,8 @@ object Defaults extends BuildCommon {
apiMappings ++= {
val dependencyCp = dependencyClasspath.value
val log = streams.value.log
if (autoAPIMappings.value) APIMappings.extract(dependencyCp, log).toMap
else Map.empty[HashedVirtualFileRef, URL]
if autoAPIMappings.value then APIMappings.extract(dependencyCp, log).toMap
else Map.empty[HashedVirtualFileRef, URI]
},
fileInputOptions := Seq("-doc-root-content", "-diagrams-dot-path"),
scalacOptions := {
@ -3088,11 +3087,11 @@ object Classpaths {
projectInfo := ModuleInfo(
name.value,
description.value,
homepage.value.map(_.toURI),
homepage.value,
startYear.value,
licenses.value.map((name, url) => (name, url.toURI)).toVector,
licenses.value.toVector,
organizationName.value,
organizationHomepage.value.map(_.toURI),
organizationHomepage.value,
scmInfo.value,
developers.value.toVector
),
@ -3517,21 +3516,18 @@ object Classpaths {
val p0 = ModuleID(organization.value, moduleName.value, version.value)
.cross((projectID / crossVersion).value)
.artifacts(artifacts.value*)
val p1 = apiURL.value match {
case Some(u) => p0.extra(SbtPomExtraProperties.POM_API_KEY -> u.toExternalForm)
val p1 = apiURL.value match
case Some(u) => p0.extra(SbtPomExtraProperties.POM_API_KEY -> u.toURL().toExternalForm)
case _ => p0
}
val p2 = versionScheme.value match {
val p2 = versionScheme.value match
case Some(x) =>
VersionSchemes.validateScheme(x)
p1.extra(SbtPomExtraProperties.VERSION_SCHEME_KEY -> x)
case _ => p1
}
val p3 = releaseNotesURL.value match {
val p3 = releaseNotesURL.value match
case Some(u) =>
p2.extra(SbtPomExtraProperties.POM_RELEASE_NOTES_KEY -> u.toExternalForm)
p2.extra(SbtPomExtraProperties.POM_RELEASE_NOTES_KEY -> u.toURL().toExternalForm)
case _ => p2
}
p3
}
def pluginProjectID: Initialize[ModuleID] =

View File

@ -10,7 +10,7 @@ package sbt
import java.nio.file.{ Path => NioPath }
import java.io.File
import java.net.{ URL, URI }
import java.net.URI
import lmcoursier.definitions.{ CacheLogger, ModuleMatchers, Reconciliation }
import lmcoursier.{ CoursierConfiguration, FallbackDependency }
import org.apache.ivy.core.module.descriptor.ModuleDescriptor
@ -379,18 +379,18 @@ object Keys {
val name = settingKey[String]("Project name.").withRank(APlusSetting)
val normalizedName = settingKey[String]("Project name transformed from mixed case and spaces to lowercase and dash-separated.").withRank(BSetting)
val description = settingKey[String]("Project description.").withRank(BSetting)
val homepage = settingKey[Option[URL]]("Project homepage.").withRank(BSetting)
val homepage = settingKey[Option[URI]]("Project homepage.").withRank(BSetting)
val startYear = settingKey[Option[Int]]("Year in which the project started.").withRank(BMinusSetting)
val licenses = settingKey[Seq[(String, URL)]]("Project licenses as (name, url) pairs.").withRank(BMinusSetting)
val licenses = settingKey[Seq[(String, URI)]]("Project licenses as (name, url) pairs.").withRank(BMinusSetting)
val organization = settingKey[String]("Organization/group ID.").withRank(APlusSetting)
val organizationName = settingKey[String]("Organization full/formal name.").withRank(BMinusSetting)
val organizationHomepage = settingKey[Option[URL]]("Organization homepage.").withRank(BMinusSetting)
val organizationHomepage = settingKey[Option[URI]]("Organization homepage.").withRank(BMinusSetting)
val developers = settingKey[List[Developer]]("List of developers implicated in the project").withRank(BMinusSetting)
val apiURL = settingKey[Option[URL]]("Base URL for API documentation.").withRank(BMinusSetting)
val apiURL = settingKey[Option[URI]]("Base URI for API documentation.").withRank(BMinusSetting)
val entryApiURL = StringAttributeKey("entryApiURL") // , "Base URL for the API documentation for a classpath entry.")
val apiMappings = taskKey[Map[HashedVirtualFileRef, URL]]("Mappings from classpath entry to API documentation base URL.").withRank(BMinusSetting)
val apiMappings = taskKey[Map[HashedVirtualFileRef, URI]]("Mappings from classpath entry to API documentation base URL.").withRank(BMinusSetting)
val autoAPIMappings = settingKey[Boolean]("If true, automatically manages mappings to the API doc URL.").withRank(BMinusSetting)
val releaseNotesURL = settingKey[Option[URL]]("URL for release notes.").withRank(BMinusSetting)
val releaseNotesURL = settingKey[Option[URI]]("URL for release notes.").withRank(BMinusSetting)
val scmInfo = settingKey[Option[ScmInfo]]("Basic SCM information for the project.").withRank(BMinusSetting)
val projectInfo = settingKey[ModuleInfo]("Addition project information like formal name, homepage, licenses etc.").withRank(CSetting)
val defaultConfiguration = settingKey[Option[Configuration]]("Defines the configuration used when none is specified for a dependency in ivyXML.").withRank(CSetting)

View File

@ -12,7 +12,7 @@ import sbt.librarymanagement.{ MavenRepository, Resolver }
import sbt.librarymanagement.ivy.Credentials
import java.io.File
import java.net.URL
import java.net.URI
import sbt.io.Path
import Path._
@ -33,11 +33,11 @@ object Opts {
def sourceUrl(u: String): Seq[String] = Seq("-doc-source-url", u)
def title(t: String): Seq[String] = Seq("-doc-title", t)
def version(v: String): Seq[String] = Seq("-doc-version", v)
def externalAPI(mappings: Iterable[(File, URL)]): Seq[String] =
def externalAPI(mappings: Iterable[(File, URI)]): Seq[String] =
if (mappings.isEmpty) Nil
else
mappings
.map { case (f, u) => s"${f.getAbsolutePath}#${u.toExternalForm}" }
.map { case (f, u) => s"${f.getAbsolutePath}#${u.toURL().toExternalForm}" }
.mkString("-doc-external-doc:", ",", "") :: Nil
}
object resolver {

View File

@ -9,7 +9,7 @@
package sbt
package coursierint
import java.net.URL
import java.net.URI
import sbt.librarymanagement._
import sbt.util.Logger
import sbt.Keys._
@ -46,10 +46,10 @@ object CoursierInputsTasks {
configurations: Seq[sbt.librarymanagement.Configuration],
sv: String,
sbv: String,
auOpt: Option[URL],
rnOpt: Option[URL],
auOpt: Option[URI],
rnOpt: Option[URI],
description: String,
homepage: Option[URL],
homepage: Option[URI],
vsOpt: Option[String],
projectPlatform: Option[String],
log: Logger

View File

@ -9,7 +9,7 @@
package sbt
package internal
import java.net.{ MalformedURLException, URI, URL }
import java.net.{ MalformedURLException, URI }
import sbt.internal.librarymanagement.mavenint.SbtPomExtraProperties
import sbt.librarymanagement.ModuleID
@ -21,15 +21,15 @@ private[sbt] object APIMappings {
def extract(
cp: Seq[Attributed[HashedVirtualFileRef]],
log: Logger
): Seq[(HashedVirtualFileRef, URL)] =
): Seq[(HashedVirtualFileRef, URI)] =
cp.flatMap(entry => extractFromEntry(entry, log))
def extractFromEntry(
entry: Attributed[HashedVirtualFileRef],
log: Logger
): Option[(HashedVirtualFileRef, URL)] =
): Option[(HashedVirtualFileRef, URI)] =
entry.get(Keys.entryApiURL) match
case Some(u) => Some((entry.data, URI(u).toURL))
case Some(u) => Some((entry.data, URI(u)))
case None =>
entry.get(Keys.moduleIDStr).flatMap { str =>
val mid = Classpaths.moduleIdJsonKeyFormat.read(str)
@ -40,22 +40,20 @@ private[sbt] object APIMappings {
entry: HashedVirtualFileRef,
mid: ModuleID,
log: Logger
): Option[(HashedVirtualFileRef, URL)] =
): Option[(HashedVirtualFileRef, URI)] =
for
urlString <- mid.extraAttributes.get(SbtPomExtraProperties.POM_API_KEY)
u <- parseURL(urlString, entry, log)
u <- parseURI(urlString, entry, log)
yield (entry, u)
private def parseURL(s: String, forEntry: HashedVirtualFileRef, log: Logger): Option[URL] =
try
Some(new URI(s).toURL)
catch {
private def parseURI(s: String, forEntry: HashedVirtualFileRef, log: Logger): Option[URI] =
try Some(new URI(s))
catch
case e: MalformedURLException =>
log.warn(s"Invalid API base URL '$s' for classpath entry '$forEntry': ${e.toString}")
log.warn(s"Invalid API base URI '$s' for classpath entry '$forEntry': ${e.toString}")
None
}
def store[A](attr: Attributed[A], entryAPI: Option[URL]): Attributed[A] =
def store[A](attr: Attributed[A], entryAPI: Option[URI]): Attributed[A] =
entryAPI match
case None => attr
case Some(u) => attr.put(Keys.entryApiURL, u.toString)