mirror of https://github.com/sbt/sbt.git
More API docs for the classpath module
This commit is contained in:
parent
50232c56af
commit
78178f8716
|
|
@ -5,7 +5,10 @@ package sbt
|
|||
|
||||
object ModuleUtilities
|
||||
{
|
||||
def getObject(className: String, loader: ClassLoader) =
|
||||
/** Reflectively loads and returns the companion object for top-level class `className` from `loader`.
|
||||
* The class name should not include the `$` that scalac appends to the underlying jvm class for
|
||||
* a companion object. */
|
||||
def getObject(className: String, loader: ClassLoader): AnyRef =
|
||||
{
|
||||
val obj = Class.forName(className + "$", true, loader)
|
||||
val singletonField = obj.getField("MODULE$")
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import scala.collection._
|
|||
|
||||
object ReflectUtilities
|
||||
{
|
||||
def transformCamelCase(name: String, separator: Char) =
|
||||
/** Converts the camelCase String `name` to lowercase separated by `separator`. */
|
||||
def transformCamelCase(name: String, separator: Char): String =
|
||||
{
|
||||
val buffer = new StringBuilder
|
||||
for(char <- name)
|
||||
|
|
@ -33,6 +34,9 @@ object ReflectUtilities
|
|||
flatMap(_.getDeclaredFields).
|
||||
map(f => (f.getName, f)):_*)
|
||||
|
||||
/** Collects all `val`s of type `T` defined on value `self`.
|
||||
* The returned Map maps the name of each `val` to its value.
|
||||
* This depends on scalac implementation details to determine what is a `val` using only Java reflection. */
|
||||
def allValsC[T](self: AnyRef, clazz: Class[T]): immutable.SortedMap[String, T] =
|
||||
{
|
||||
var mappings = new immutable.TreeMap[String, T]
|
||||
|
|
@ -51,7 +55,14 @@ object ReflectUtilities
|
|||
}
|
||||
mappings
|
||||
}
|
||||
|
||||
/** Collects all `val`s of type `T` defined on value `self`.
|
||||
* The returned Map maps the name of each `val` to its value.
|
||||
* This requires an available `Manifest` for `T` and depends on scalac implementation details to determine
|
||||
* what is a `val` using only Java reflection. */
|
||||
def allVals[T](self: AnyRef)(implicit mt: scala.reflect.Manifest[T]): immutable.SortedMap[String, T] =
|
||||
allValsC(self, mt.runtimeClass).asInstanceOf[immutable.SortedMap[String,T]]
|
||||
}
|
||||
|
||||
/** An exception to indicate that while traversing the `val`s for an instance of `className`, the `val` named `valName` was `null`. */
|
||||
final class UninitializedVal(val valName: String, val className: String) extends RuntimeException("val " + valName + " in class " + className + " was null.\nThis is probably an initialization problem and a 'lazy val' should be used.")
|
||||
|
|
@ -105,6 +105,8 @@ final class FilteredLoader(parent: ClassLoader, filter: ClassFilter) extends Cla
|
|||
throw new ClassNotFoundException(className)
|
||||
}
|
||||
}
|
||||
|
||||
/** Defines a filter on class names. */
|
||||
trait ClassFilter
|
||||
{
|
||||
def include(className: String): Boolean
|
||||
|
|
@ -114,18 +116,31 @@ abstract class PackageFilter(packages: Iterable[String]) extends ClassFilter
|
|||
require(packages.forall(_.endsWith(".")))
|
||||
protected final def matches(className: String): Boolean = packages.exists(className.startsWith)
|
||||
}
|
||||
/** Excludes class names that begin with one of the packages in `exclude`.
|
||||
* Each package name in `packages` must end with a `.` */
|
||||
final class ExcludePackagesFilter(exclude: Iterable[String]) extends PackageFilter(exclude)
|
||||
{
|
||||
def include(className: String): Boolean = !matches(className)
|
||||
}
|
||||
|
||||
/** Includes class names that begin with one of the packages in `include`.
|
||||
* Each package name in `include` must end with a `.` */
|
||||
final class IncludePackagesFilter(include: Iterable[String]) extends PackageFilter(include)
|
||||
{
|
||||
def include(className: String): Boolean = matches(className)
|
||||
}
|
||||
|
||||
/** Configures a [[NativeCopyLoader]].
|
||||
* The loader will provide native libraries listed in `explicitLibraries` and on `searchPaths` by copying them to `tempDirectory`.
|
||||
* If `tempDirectory` is unique to the class loader, this ensures that the class loader gets a unique path for
|
||||
* the native library and avoids the restriction on a native library being loaded by a single class loader. */
|
||||
final class NativeCopyConfig(val tempDirectory: File, val explicitLibraries: Seq[File], val searchPaths: Seq[File])
|
||||
|
||||
/** Loads native libraries from a temporary location in order to work around the jvm native library uniqueness restriction.
|
||||
* See [[NativeCopyConfig]] for configuration details. */
|
||||
trait NativeCopyLoader extends ClassLoader
|
||||
{
|
||||
/** Configures this loader. See [[NativeCopyConfig]] for details. */
|
||||
protected val config: NativeCopyConfig
|
||||
import config._
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package classpath
|
|||
import java.net.URL
|
||||
import java.util.Enumeration
|
||||
|
||||
/** A class loader that always fails to load classes and resources. */
|
||||
final class NullLoader extends ClassLoader
|
||||
{
|
||||
override final def loadClass(className: String, resolve: Boolean): Class[_] = throw new ClassNotFoundException("No classes can be loaded from the null loader")
|
||||
|
|
@ -14,7 +15,20 @@ final class NullLoader extends ClassLoader
|
|||
override def getResources(name: String): Enumeration[URL] = null
|
||||
}
|
||||
|
||||
/** Exception thrown when `loaderA` and `loaderB` load a different Class for the same name. */
|
||||
class DifferentLoaders(message: String, val loaderA: ClassLoader, val loaderB: ClassLoader) extends ClassNotFoundException(message)
|
||||
|
||||
/** A ClassLoader with two parents `parentA` and `parentB`. The predicates direct lookups towards one parent or the other.
|
||||
*
|
||||
* If `aOnlyClasses` returns `true` for a class name, class lookup delegates to `parentA` only.
|
||||
* Otherwise, if `bOnlyClasses` returns `true` for a class name, class lookup delegates to `parentB` only.
|
||||
* If both `aOnlyClasses` and `bOnlyClasses` are `false` for a given class name, both class loaders must load the same Class or
|
||||
* a [[DifferentLoaders]] exception is thrown.
|
||||
*
|
||||
* If `aOnlyResources` is `true` for a resource path, lookup delegates to `parentA` only.
|
||||
* Otherwise, if `bOnlyResources` is `true` for a resource path, lookup delegates to `parentB` only.
|
||||
* If neither are `true` for a resource path and either `parentA` or `parentB` return a valid URL, that valid URL is returned.
|
||||
**/
|
||||
class DualLoader(parentA: ClassLoader, aOnlyClasses: String => Boolean, aOnlyResources: String => Boolean,
|
||||
parentB: ClassLoader, bOnlyClasses: String => Boolean, bOnlyResources: String => Boolean) extends ClassLoader(new NullLoader)
|
||||
{
|
||||
|
|
@ -76,6 +90,7 @@ class DualLoader(parentA: ClassLoader, aOnlyClasses: String => Boolean, aOnlyRes
|
|||
}
|
||||
}
|
||||
|
||||
/** Concatenates `a` and `b` into a single `Enumeration`.*/
|
||||
final class DualEnumeration[T](a: Enumeration[T], b: Enumeration[T]) extends Enumeration[T]
|
||||
{
|
||||
// invariant: current.hasMoreElements or current eq b
|
||||
|
|
|
|||
|
|
@ -10,10 +10,17 @@ package classpath
|
|||
|
||||
object RawURL
|
||||
{
|
||||
/** Constructs a URL with scheme `raw` and path `file` that will return the bytes for `value` in the platform default encoding
|
||||
* when a connection to the URL is opened. */
|
||||
def apply(file: String, value: String): URL =
|
||||
apply(file, value.getBytes)
|
||||
|
||||
/** Constructs a URL with scheme `raw` and path `file` that will return the bytes `value` when a connection to the URL is opened. */
|
||||
def apply(file: String, value: Array[Byte]): URL =
|
||||
apply(file)(new ByteArrayInputStream(value))
|
||||
|
||||
/** Constructs a URL with scheme `raw` and path `file` that will use `value` to construct the `InputStream` used when a connection
|
||||
* to the URL is opened. */
|
||||
def apply(file: String)(value: => InputStream): URL =
|
||||
new URL("raw", null, -1, file, new RawStreamHandler(value))
|
||||
|
||||
|
|
@ -31,14 +38,20 @@ object RawURL
|
|||
}
|
||||
}
|
||||
|
||||
/** A ClassLoader that looks up resource requests in a `Map` prior to the base ClassLoader's resource lookups. */
|
||||
trait RawResources extends FixedResources
|
||||
{
|
||||
/** The map from resource paths to the raw String content to provide via the URL returned by [[findResource]] or [[findResources]]. */
|
||||
protected def resources: Map[String, String]
|
||||
override protected final val resourceURL = resources.transform(RawURL.apply)
|
||||
}
|
||||
|
||||
/** A ClassLoader that looks up resource requests in a `Map` prior to the base ClassLoader's resource lookups. */
|
||||
trait FixedResources extends ClassLoader
|
||||
{
|
||||
/** The map from resource paths to URL to provide in [[findResource]] and [[findResources]]. */
|
||||
protected def resourceURL: Map[String, URL]
|
||||
|
||||
override def findResource(s: String): URL = resourceURL.getOrElse(s, super.findResource(s))
|
||||
|
||||
import java.util.Collections.{enumeration, singletonList}
|
||||
|
|
|
|||
Loading…
Reference in New Issue