mirror of https://github.com/sbt/sbt.git
ResolutionClassLoader (WIP)
This commit is contained in:
parent
da98fbca2b
commit
aa2a909fbd
|
|
@ -97,6 +97,9 @@ case class Launch(
|
|||
@ExtraName("M")
|
||||
@ExtraName("main")
|
||||
mainClass: String,
|
||||
@ExtraName("c")
|
||||
@HelpMessage("Assume coursier is a dependency of the launched app, and share the coursier dependency of the launcher with it - allows the launched app to get the resolution that launched it via ResolutionClassLoader")
|
||||
addCoursier: Boolean,
|
||||
@Recurse
|
||||
common: CommonOptions
|
||||
) extends CoursierCommand {
|
||||
|
|
@ -110,7 +113,29 @@ case class Launch(
|
|||
}
|
||||
}
|
||||
|
||||
val helper = new Helper(common, rawDependencies)
|
||||
val extraForceVersions =
|
||||
if (addCoursier)
|
||||
???
|
||||
else
|
||||
Seq.empty[String]
|
||||
|
||||
val dontFilterOut =
|
||||
if (addCoursier) {
|
||||
val url = classOf[coursier.core.Resolution].getProtectionDomain.getCodeSource.getLocation
|
||||
|
||||
if (url.getProtocol == "file")
|
||||
Seq(new File(url.getPath))
|
||||
else {
|
||||
Console.err.println(s"Cannot get the location of the JAR of coursier ($url not a file URL)")
|
||||
sys.exit(255)
|
||||
}
|
||||
} else
|
||||
Seq.empty[File]
|
||||
|
||||
val helper = new Helper(
|
||||
common.copy(forceVersion = common.forceVersion ++ extraForceVersions),
|
||||
rawDependencies
|
||||
)
|
||||
|
||||
val files0 = helper.fetch(sources = false, javadoc = false)
|
||||
|
||||
|
|
@ -118,7 +143,7 @@ case class Launch(
|
|||
files0.map(_.toURI.toURL).toArray,
|
||||
new ClasspathFilter(
|
||||
Thread.currentThread().getContextClassLoader,
|
||||
Coursier.baseCp.map(new File(_)).toSet,
|
||||
Coursier.baseCp.map(new File(_)).toSet -- dontFilterOut,
|
||||
exclude = true
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
package coursier
|
||||
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
|
||||
import coursier.util.ClasspathFilter
|
||||
|
||||
class ResolutionClassLoader(
|
||||
val resolution: Resolution,
|
||||
val artifacts: Seq[(Dependency, Artifact, File)],
|
||||
parent: ClassLoader
|
||||
) extends URLClassLoader(
|
||||
artifacts.map { case (_, _, f) => f.toURI.toURL }.toArray,
|
||||
parent
|
||||
) {
|
||||
|
||||
/**
|
||||
* Filtered version of this `ClassLoader`, exposing only `dependencies` and their
|
||||
* their transitive dependencies, and filtering out the other dependencies from
|
||||
* `resolution` - for `ClassLoader` isolation.
|
||||
*
|
||||
* An application launched by `coursier launch -C` has `ResolutionClassLoader` set as its
|
||||
* context `ClassLoader` (can be obtain with `Thread.currentThread().getContextClassLoader`).
|
||||
* If it aims at doing `ClassLoader` isolation, exposing only a dependency `dep` to the isolated
|
||||
* things, `filter(dep)` provides a `ClassLoader` that loaded `dep` and all its transitive
|
||||
* dependencies through the same loader as the contextual one, but that "exposes" only
|
||||
* `dep` and its transitive dependencies, nothing more.
|
||||
*/
|
||||
def filter(dependencies: Set[Dependency]): ClassLoader = {
|
||||
val subRes = resolution.subset(dependencies)
|
||||
val subArtifacts = subRes.dependencyArtifacts.map { case (_, a) => a }.toSet
|
||||
val subFiles = artifacts.collect { case (_, a, f) if subArtifacts(a) => f }
|
||||
|
||||
new ClasspathFilter(this, subFiles.toSet, exclude = false)
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue