mirror of https://github.com/sbt/sbt.git
69 lines
2.2 KiB
Scala
69 lines
2.2 KiB
Scala
package xsbt.boot
|
|
|
|
import Pre._
|
|
import java.io.{File, FileFilter}
|
|
import java.net.{URL, URLClassLoader}
|
|
import java.util.concurrent.Callable
|
|
|
|
trait Provider extends NotNull
|
|
{
|
|
def configuration: UpdateConfiguration
|
|
def baseDirectories: List[File]
|
|
def testLoadClasses: List[String]
|
|
def target: UpdateTarget
|
|
def failLabel: String
|
|
def parentLoader: ClassLoader
|
|
def lockFile: File
|
|
|
|
def classpath = Provider.getJars(baseDirectories)
|
|
|
|
def retrieveFailed: Nothing = fail("")
|
|
def retrieveCorrupt(missing: Iterable[String]): Nothing = fail(": missing " + missing.mkString(", "))
|
|
private def fail(extra: String) =
|
|
throw new xsbti.RetrieveException(versionString, "Could not retrieve " + failLabel + extra)
|
|
private def versionString: String = target match { case UpdateScala => configuration.scalaVersion; case a: UpdateApp => Version.get(a.id.version) }
|
|
|
|
val (jars, loader) = Locks(lockFile, new initialize)
|
|
private final class initialize extends Callable[(Array[File], ClassLoader)]
|
|
{
|
|
def call =
|
|
{
|
|
val (existingJars, existingLoader) = createLoader
|
|
if(Provider.getMissing(existingLoader, testLoadClasses).isEmpty)
|
|
(existingJars, existingLoader)
|
|
else
|
|
{
|
|
val retrieveSuccess = ( new Update(configuration) )(target)
|
|
if(retrieveSuccess)
|
|
{
|
|
val (newJars, newLoader) = createLoader
|
|
val missing = Provider.getMissing(newLoader, testLoadClasses)
|
|
if(missing.isEmpty) (newJars, newLoader) else retrieveCorrupt(missing)
|
|
}
|
|
else
|
|
retrieveFailed
|
|
}
|
|
}
|
|
def createLoader =
|
|
{
|
|
val jars = classpath
|
|
(jars, new URLClassLoader(jars.map(_.toURI.toURL), parentLoader) )
|
|
}
|
|
}
|
|
}
|
|
|
|
object Provider
|
|
{
|
|
def getJars(directories: List[File]): Array[File] = toArray(directories.flatMap(directory => wrapNull(directory.listFiles(JarFilter))))
|
|
def wrapNull(a: Array[File]): Array[File] = if(a == null) Array() else a
|
|
|
|
object JarFilter extends FileFilter
|
|
{
|
|
def accept(file: File) = !file.isDirectory && file.getName.endsWith(".jar")
|
|
}
|
|
def getMissing(loader: ClassLoader, classes: Iterable[String]): Iterable[String] =
|
|
{
|
|
def classMissing(c: String) = try { Class.forName(c, false, loader); false } catch { case e: ClassNotFoundException => true }
|
|
classes.toList.filter(classMissing)
|
|
}
|
|
} |