2009-09-26 08:18:04 +02:00
|
|
|
package xsbt.boot
|
|
|
|
|
|
2009-10-18 04:40:02 +02:00
|
|
|
import Pre._
|
2009-09-26 08:18:04 +02:00
|
|
|
import java.io.{File, FileFilter}
|
|
|
|
|
import java.net.{URL, URLClassLoader}
|
2009-10-24 19:07:42 +02:00
|
|
|
import java.util.concurrent.Callable
|
2009-09-26 08:18:04 +02:00
|
|
|
|
|
|
|
|
trait Provider extends NotNull
|
|
|
|
|
{
|
2009-09-27 20:39:26 +02:00
|
|
|
def configuration: UpdateConfiguration
|
2009-10-18 04:40:02 +02:00
|
|
|
def baseDirectories: List[File]
|
|
|
|
|
def testLoadClasses: List[String]
|
2009-09-27 20:39:26 +02:00
|
|
|
def target: UpdateTarget
|
2009-09-26 08:18:04 +02:00
|
|
|
def failLabel: String
|
|
|
|
|
def parentLoader: ClassLoader
|
2009-10-24 19:07:42 +02:00
|
|
|
def lockFile: File
|
2009-09-26 08:18:04 +02:00
|
|
|
|
2009-10-24 19:07:42 +02:00
|
|
|
val (jars, loader) = Locks(lockFile, new initialize)
|
|
|
|
|
private final class initialize extends Callable[(Array[File], ClassLoader)]
|
2009-09-26 08:18:04 +02:00
|
|
|
{
|
2009-10-24 19:07:42 +02:00
|
|
|
def call =
|
2009-09-26 08:18:04 +02:00
|
|
|
{
|
2009-10-24 19:07:42 +02:00
|
|
|
val (existingJars, existingLoader) = createLoader
|
|
|
|
|
if(Provider.needsUpdate(existingLoader, testLoadClasses))
|
|
|
|
|
{
|
|
|
|
|
( new Update(configuration) )(target)
|
|
|
|
|
val (newJars, newLoader) = createLoader
|
|
|
|
|
Provider.failIfMissing(newLoader, testLoadClasses, failLabel)
|
|
|
|
|
(newJars, newLoader)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
(existingJars, existingLoader)
|
|
|
|
|
}
|
|
|
|
|
def createLoader =
|
|
|
|
|
{
|
|
|
|
|
val jars = Provider.getJars(baseDirectories)
|
|
|
|
|
(jars, new URLClassLoader(jars.map(_.toURI.toURL), parentLoader) )
|
2009-09-26 08:18:04 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-24 19:07:42 +02:00
|
|
|
object Provider
|
2009-09-26 08:18:04 +02:00
|
|
|
{
|
2009-10-24 19:07:42 +02:00
|
|
|
def getJars(directories: List[File]): Array[File] = toArray(directories.flatMap(directory => wrapNull(directory.listFiles(JarFilter))))
|
2009-09-26 08:18:04 +02:00
|
|
|
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 failIfMissing(loader: ClassLoader, classes: Iterable[String], label: String) =
|
2009-10-18 04:40:02 +02:00
|
|
|
checkTarget(loader, classes, (), missing => error("Could not retrieve " + label + ": missing " + missing.mkString(", ")))
|
2009-09-26 08:18:04 +02:00
|
|
|
def needsUpdate(loader: ClassLoader, classes: Iterable[String]) = checkTarget(loader, classes, false, x => true)
|
|
|
|
|
def checkTarget[T](loader: ClassLoader, classes: Iterable[String], ifSuccess: => T, ifFailure: Iterable[String] => T): T =
|
|
|
|
|
{
|
|
|
|
|
def classMissing(c: String) = try { Class.forName(c, false, loader); false } catch { case e: ClassNotFoundException => true }
|
2009-10-18 04:40:02 +02:00
|
|
|
val missing = classes.toList.filter(classMissing)
|
2009-09-26 08:18:04 +02:00
|
|
|
if(missing.isEmpty) ifSuccess else ifFailure(missing)
|
|
|
|
|
}
|
|
|
|
|
}
|