mirror of https://github.com/sbt/sbt.git
better location for class loaders (ClassLoaders.scala)
This commit is contained in:
parent
897f9ca3d1
commit
d09aab03be
|
|
@ -42,3 +42,90 @@ class SelfFirstLoader(classpath: Seq[URL], parent: ClassLoader) extends LoaderBa
|
||||||
catch { case _: ClassNotFoundException => defaultLoadClass(className) }
|
catch { case _: ClassNotFoundException => defaultLoadClass(className) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class IntermediateLoader(urls: Array[URL], parent: ClassLoader) extends LoaderBase(urls, parent)
|
||||||
|
{
|
||||||
|
def doLoadClass(className: String): Class[_] =
|
||||||
|
{
|
||||||
|
// if this loader is asked to load an sbt class, it must be because the project we are building is sbt itself,
|
||||||
|
// so we want to load the version of classes on the project classpath, not the parent
|
||||||
|
if(className.startsWith(Loaders.SbtPackage))
|
||||||
|
findClass(className)
|
||||||
|
else
|
||||||
|
defaultLoadClass(className)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Delegates class loading to `parent` for all classes included by `filter`. An attempt to load classes excluded by `filter`
|
||||||
|
* results in a `ClassNotFoundException`.*/
|
||||||
|
class FilteredLoader(parent: ClassLoader, filter: ClassFilter) extends ClassLoader(parent)
|
||||||
|
{
|
||||||
|
require(parent != null) // included because a null parent is legitimate in Java
|
||||||
|
def this(parent: ClassLoader, excludePackages: Iterable[String]) = this(parent, new ExcludePackagesFilter(excludePackages))
|
||||||
|
|
||||||
|
@throws(classOf[ClassNotFoundException])
|
||||||
|
override final def loadClass(className: String, resolve: Boolean): Class[_] =
|
||||||
|
{
|
||||||
|
if(filter.include(className))
|
||||||
|
super.loadClass(className, resolve)
|
||||||
|
else
|
||||||
|
throw new ClassNotFoundException(className)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private class SelectiveLoader(urls: Array[URL], parent: ClassLoader, filter: ClassFilter) extends URLClassLoader(urls, parent)
|
||||||
|
{
|
||||||
|
require(parent != null) // included because a null parent is legitimate in Java
|
||||||
|
def this(urls: Array[URL], parent: ClassLoader, includePackages: Iterable[String]) = this(urls, parent, new IncludePackagesFilter(includePackages))
|
||||||
|
|
||||||
|
@throws(classOf[ClassNotFoundException])
|
||||||
|
override final def loadClass(className: String, resolve: Boolean): Class[_] =
|
||||||
|
{
|
||||||
|
if(filter.include(className))
|
||||||
|
super.loadClass(className, resolve)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val loaded = parent.loadClass(className)
|
||||||
|
if(resolve)
|
||||||
|
resolveClass(loaded)
|
||||||
|
loaded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trait ClassFilter
|
||||||
|
{
|
||||||
|
def include(className: String): Boolean
|
||||||
|
}
|
||||||
|
abstract class PackageFilter(packages: Iterable[String]) extends ClassFilter
|
||||||
|
{
|
||||||
|
require(packages.forall(_.endsWith(".")))
|
||||||
|
protected final def matches(className: String): Boolean = packages.exists(className.startsWith)
|
||||||
|
}
|
||||||
|
class ExcludePackagesFilter(exclude: Iterable[String]) extends PackageFilter(exclude)
|
||||||
|
{
|
||||||
|
def include(className: String): Boolean = !matches(className)
|
||||||
|
}
|
||||||
|
class IncludePackagesFilter(include: Iterable[String]) extends PackageFilter(include)
|
||||||
|
{
|
||||||
|
def include(className: String): Boolean = matches(className)
|
||||||
|
}
|
||||||
|
|
||||||
|
private[sbt] class LazyFrameworkLoader(runnerClassName: String, urls: Array[URL], parent: ClassLoader, grandparent: ClassLoader)
|
||||||
|
extends LoaderBase(urls, parent)
|
||||||
|
{
|
||||||
|
def doLoadClass(className: String): Class[_] =
|
||||||
|
{
|
||||||
|
if(Loaders.isNestedOrSelf(className, runnerClassName))
|
||||||
|
findClass(className)
|
||||||
|
else if(Loaders.isSbtClass(className)) // we circumvent the parent loader because we know that we want the
|
||||||
|
grandparent.loadClass(className) // version of sbt that is currently the builder (not the project being built)
|
||||||
|
else
|
||||||
|
parent.loadClass(className)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private object Loaders
|
||||||
|
{
|
||||||
|
val SbtPackage = "sbt."
|
||||||
|
def isNestedOrSelf(className: String, checkAgainst: String) =
|
||||||
|
className == checkAgainst || className.startsWith(checkAgainst + "$")
|
||||||
|
def isSbtClass(className: String) = className.startsWith(Loaders.SbtPackage)
|
||||||
|
}
|
||||||
|
|
@ -129,89 +129,3 @@ object ClasspathUtilities
|
||||||
set
|
set
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IntermediateLoader(urls: Array[URL], parent: ClassLoader) extends LoaderBase(urls, parent)
|
|
||||||
{
|
|
||||||
def doLoadClass(className: String): Class[_] =
|
|
||||||
{
|
|
||||||
// if this loader is asked to load an sbt class, it must be because the project we are building is sbt itself,
|
|
||||||
// so we want to load the version of classes on the project classpath, not the parent
|
|
||||||
if(className.startsWith(Loaders.SbtPackage))
|
|
||||||
findClass(className)
|
|
||||||
else
|
|
||||||
defaultLoadClass(className)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** Delegates class loading to `parent` for all classes included by `filter`. An attempt to load classes excluded by `filter`
|
|
||||||
* results in a `ClassNotFoundException`.*/
|
|
||||||
class FilteredLoader(parent: ClassLoader, filter: ClassFilter) extends ClassLoader(parent)
|
|
||||||
{
|
|
||||||
require(parent != null) // included because a null parent is legitimate in Java
|
|
||||||
def this(parent: ClassLoader, excludePackages: Iterable[String]) = this(parent, new ExcludePackagesFilter(excludePackages))
|
|
||||||
|
|
||||||
@throws(classOf[ClassNotFoundException])
|
|
||||||
override final def loadClass(className: String, resolve: Boolean): Class[_] =
|
|
||||||
{
|
|
||||||
if(filter.include(className))
|
|
||||||
super.loadClass(className, resolve)
|
|
||||||
else
|
|
||||||
throw new ClassNotFoundException(className)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private class SelectiveLoader(urls: Array[URL], parent: ClassLoader, filter: ClassFilter) extends URLClassLoader(urls, parent)
|
|
||||||
{
|
|
||||||
require(parent != null) // included because a null parent is legitimate in Java
|
|
||||||
def this(urls: Array[URL], parent: ClassLoader, includePackages: Iterable[String]) = this(urls, parent, new IncludePackagesFilter(includePackages))
|
|
||||||
|
|
||||||
@throws(classOf[ClassNotFoundException])
|
|
||||||
override final def loadClass(className: String, resolve: Boolean): Class[_] =
|
|
||||||
{
|
|
||||||
if(filter.include(className))
|
|
||||||
super.loadClass(className, resolve)
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val loaded = parent.loadClass(className)
|
|
||||||
if(resolve)
|
|
||||||
resolveClass(loaded)
|
|
||||||
loaded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trait ClassFilter
|
|
||||||
{
|
|
||||||
def include(className: String): Boolean
|
|
||||||
}
|
|
||||||
abstract class PackageFilter(packages: Iterable[String]) extends ClassFilter
|
|
||||||
{
|
|
||||||
require(packages.forall(_.endsWith(".")))
|
|
||||||
protected final def matches(className: String): Boolean = packages.exists(className.startsWith)
|
|
||||||
}
|
|
||||||
class ExcludePackagesFilter(exclude: Iterable[String]) extends PackageFilter(exclude)
|
|
||||||
{
|
|
||||||
def include(className: String): Boolean = !matches(className)
|
|
||||||
}
|
|
||||||
class IncludePackagesFilter(include: Iterable[String]) extends PackageFilter(include)
|
|
||||||
{
|
|
||||||
def include(className: String): Boolean = matches(className)
|
|
||||||
}
|
|
||||||
|
|
||||||
private[sbt] class LazyFrameworkLoader(runnerClassName: String, urls: Array[URL], parent: ClassLoader, grandparent: ClassLoader)
|
|
||||||
extends LoaderBase(urls, parent)
|
|
||||||
{
|
|
||||||
def doLoadClass(className: String): Class[_] =
|
|
||||||
{
|
|
||||||
if(Loaders.isNestedOrSelf(className, runnerClassName))
|
|
||||||
findClass(className)
|
|
||||||
else if(Loaders.isSbtClass(className)) // we circumvent the parent loader because we know that we want the
|
|
||||||
grandparent.loadClass(className) // version of sbt that is currently the builder (not the project being built)
|
|
||||||
else
|
|
||||||
parent.loadClass(className)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private object Loaders
|
|
||||||
{
|
|
||||||
val SbtPackage = "sbt."
|
|
||||||
def isNestedOrSelf(className: String, checkAgainst: String) =
|
|
||||||
className == checkAgainst || className.startsWith(checkAgainst + "$")
|
|
||||||
def isSbtClass(className: String) = className.startsWith(Loaders.SbtPackage)
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue