2009-09-26 08:18:04 +02:00
|
|
|
package xsbt.boot
|
2009-08-21 14:12:43 +02:00
|
|
|
|
2009-10-18 04:40:02 +02:00
|
|
|
import Pre._
|
2009-10-16 00:10:11 +02:00
|
|
|
import java.io.File
|
2009-09-27 20:39:26 +02:00
|
|
|
import java.net.URL
|
2009-08-21 14:12:43 +02:00
|
|
|
|
2009-09-26 08:18:04 +02:00
|
|
|
object Launch
|
2009-08-21 14:12:43 +02:00
|
|
|
{
|
2009-10-18 04:40:02 +02:00
|
|
|
val start = System.currentTimeMillis
|
|
|
|
|
def time(label: String) = System.out.println(label + " : " + (System.currentTimeMillis - start) / 1000.0 + " s")
|
|
|
|
|
def apply(arguments: List[String]): Unit = apply( (new File("")).getAbsoluteFile , arguments )
|
2009-10-02 04:59:02 +02:00
|
|
|
|
2009-10-18 04:40:02 +02:00
|
|
|
def apply(currentDirectory: File, arguments: List[String]): Unit =
|
2009-09-27 20:39:26 +02:00
|
|
|
Configuration.find(arguments, currentDirectory) match { case (configLocation, newArguments) => configured(currentDirectory, configLocation, newArguments) }
|
|
|
|
|
|
2009-10-18 04:40:02 +02:00
|
|
|
def configured(currentDirectory: File, configLocation: URL, arguments: List[String]): Unit =
|
2009-10-02 04:59:02 +02:00
|
|
|
{
|
2009-10-18 04:40:02 +02:00
|
|
|
time("found boot config")
|
2009-10-02 04:59:02 +02:00
|
|
|
val config = Configuration.parse(configLocation, currentDirectory)
|
2009-10-18 04:40:02 +02:00
|
|
|
time("parsed")
|
2009-10-02 04:59:02 +02:00
|
|
|
Find(config, currentDirectory) match { case (resolved, baseDirectory) => parsed(baseDirectory, resolved, arguments) }
|
|
|
|
|
}
|
2009-10-18 04:40:02 +02:00
|
|
|
def parsed(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Unit =
|
2009-10-15 02:53:15 +02:00
|
|
|
{
|
2009-10-18 04:40:02 +02:00
|
|
|
time("found working directory")
|
2009-10-15 02:53:15 +02:00
|
|
|
val propertiesFile = parsed.boot.properties
|
|
|
|
|
import parsed.boot.{enableQuick, promptCreate, promptFill}
|
2009-10-18 04:40:02 +02:00
|
|
|
if(isNonEmpty(promptCreate) && !propertiesFile.exists)
|
2009-10-15 02:53:15 +02:00
|
|
|
Initialize.create(propertiesFile, promptCreate, enableQuick, parsed.appProperties)
|
|
|
|
|
else if(promptFill)
|
|
|
|
|
Initialize.fill(propertiesFile, parsed.appProperties)
|
2009-10-18 04:40:02 +02:00
|
|
|
time("initialized")
|
2009-10-15 02:53:15 +02:00
|
|
|
initialized(currentDirectory, parsed, arguments)
|
|
|
|
|
}
|
2009-10-18 04:40:02 +02:00
|
|
|
def initialized(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Unit =
|
|
|
|
|
{
|
|
|
|
|
val resolved = ResolveVersions(parsed)
|
|
|
|
|
time("resolved")
|
|
|
|
|
explicit(currentDirectory, resolved, arguments)
|
|
|
|
|
}
|
2009-10-02 04:59:02 +02:00
|
|
|
|
2009-10-18 04:40:02 +02:00
|
|
|
def explicit(currentDirectory: File, explicit: LaunchConfiguration, arguments: List[String]): Unit =
|
2009-09-27 20:39:26 +02:00
|
|
|
launch( run(new Launch(explicit.boot.directory, explicit.repositories)) ) (
|
2009-10-18 04:40:02 +02:00
|
|
|
new RunConfiguration(explicit.getScalaVersion, explicit.app.toID, currentDirectory, arguments) )
|
2009-09-27 20:39:26 +02:00
|
|
|
|
2009-10-02 04:59:02 +02:00
|
|
|
def run(launcher: xsbti.Launcher)(config: RunConfiguration): xsbti.MainResult =
|
2009-08-21 14:12:43 +02:00
|
|
|
{
|
2009-09-27 20:39:26 +02:00
|
|
|
import config._
|
2009-09-26 08:18:04 +02:00
|
|
|
val scalaProvider: xsbti.ScalaProvider = launcher.getScala(scalaVersion)
|
|
|
|
|
val appProvider: xsbti.AppProvider = scalaProvider.app(app)
|
2009-10-18 04:40:02 +02:00
|
|
|
val appConfig: xsbti.AppConfiguration = new AppConfiguration(toArray(arguments), workingDirectory, appProvider)
|
|
|
|
|
|
|
|
|
|
time("pre-load")
|
|
|
|
|
val main = appProvider.newMain()
|
|
|
|
|
time("loaded")
|
|
|
|
|
val result = main.run(appConfig)
|
|
|
|
|
time("ran")
|
|
|
|
|
result
|
2009-09-27 20:39:26 +02:00
|
|
|
}
|
|
|
|
|
final def launch(run: RunConfiguration => xsbti.MainResult)(config: RunConfiguration)
|
|
|
|
|
{
|
|
|
|
|
run(config) match
|
2009-08-21 14:12:43 +02:00
|
|
|
{
|
2009-09-26 08:18:04 +02:00
|
|
|
case e: xsbti.Exit => System.exit(e.code)
|
2009-10-18 04:40:02 +02:00
|
|
|
case r: xsbti.Reboot => launch(run)(new RunConfiguration(r.scalaVersion, r.app, r.baseDirectory, r.arguments.toList))
|
2009-09-26 08:18:04 +02:00
|
|
|
case x => throw new BootException("Invalid main result: " + x + (if(x eq null) "" else " (class: " + x.getClass + ")"))
|
2009-08-21 14:12:43 +02:00
|
|
|
}
|
2009-08-24 04:21:15 +02:00
|
|
|
}
|
2009-09-26 08:18:04 +02:00
|
|
|
}
|
2009-10-18 04:40:02 +02:00
|
|
|
final class RunConfiguration(val scalaVersion: String, val app: xsbti.ApplicationID, val workingDirectory: File, val arguments: List[String]) extends NotNull
|
2009-09-05 18:19:34 +02:00
|
|
|
|
2009-09-26 08:18:04 +02:00
|
|
|
import BootConfiguration.{appDirectoryName, baseDirectoryName, ScalaDirectoryName, TestLoadScalaClasses}
|
2009-10-18 04:40:02 +02:00
|
|
|
class Launch(val bootDirectory: File, repositories: List[Repository]) extends xsbti.Launcher
|
2009-09-26 08:18:04 +02:00
|
|
|
{
|
2009-10-18 04:40:02 +02:00
|
|
|
private val scalaProviders = new Cache[String, ScalaProvider](new ScalaProvider(_))
|
|
|
|
|
def getScala(version: String): xsbti.ScalaProvider = scalaProviders(version)
|
2009-09-26 08:18:04 +02:00
|
|
|
|
2009-10-10 01:12:14 +02:00
|
|
|
lazy val topLoader = new BootFilteredLoader(getClass.getClassLoader)
|
|
|
|
|
|
2009-10-15 00:05:53 +02:00
|
|
|
def globalLock: xsbti.GlobalLock = Locks
|
|
|
|
|
|
2009-09-26 08:18:04 +02:00
|
|
|
class ScalaProvider(val version: String) extends xsbti.ScalaProvider with Provider
|
2009-08-21 14:12:43 +02:00
|
|
|
{
|
2009-09-26 08:18:04 +02:00
|
|
|
def launcher: xsbti.Launcher = Launch.this
|
2009-10-10 01:12:14 +02:00
|
|
|
def parentLoader = topLoader
|
2009-10-02 04:59:02 +02:00
|
|
|
|
2009-09-27 20:39:26 +02:00
|
|
|
lazy val configuration = new UpdateConfiguration(bootDirectory, version, repositories)
|
|
|
|
|
lazy val libDirectory = new File(configuration.bootDirectory, baseDirectoryName(version))
|
2009-09-26 08:18:04 +02:00
|
|
|
lazy val scalaHome = new File(libDirectory, ScalaDirectoryName)
|
2009-09-27 20:39:26 +02:00
|
|
|
def compilerJar = new File(scalaHome, "scala-compiler.jar")
|
|
|
|
|
def libraryJar = new File(scalaHome, "scala-library.jar")
|
2009-10-18 04:40:02 +02:00
|
|
|
def baseDirectories = List(scalaHome)
|
2009-09-26 08:18:04 +02:00
|
|
|
def testLoadClasses = TestLoadScalaClasses
|
2009-09-27 20:39:26 +02:00
|
|
|
def target = UpdateScala
|
2009-09-26 08:18:04 +02:00
|
|
|
def failLabel = "Scala " + version
|
2009-08-21 14:12:43 +02:00
|
|
|
|
2009-09-26 08:18:04 +02:00
|
|
|
def app(id: xsbti.ApplicationID): xsbti.AppProvider = new AppProvider(id)
|
|
|
|
|
|
|
|
|
|
class AppProvider(val id: xsbti.ApplicationID) extends xsbti.AppProvider with Provider
|
2009-08-21 14:12:43 +02:00
|
|
|
{
|
2009-09-26 08:18:04 +02:00
|
|
|
def scalaProvider: xsbti.ScalaProvider = ScalaProvider.this
|
2009-09-27 20:39:26 +02:00
|
|
|
def configuration = ScalaProvider.this.configuration
|
2009-09-26 08:18:04 +02:00
|
|
|
lazy val appHome = new File(libDirectory, appDirectoryName(id, File.separator))
|
|
|
|
|
def parentLoader = ScalaProvider.this.loader
|
2009-10-18 04:40:02 +02:00
|
|
|
def baseDirectories = appHome :: id.mainComponents.map(components.componentLocation).toList
|
|
|
|
|
def testLoadClasses = List(id.mainClass)
|
2009-09-27 20:39:26 +02:00
|
|
|
def target = new UpdateApp(Application(id))
|
2009-09-26 08:18:04 +02:00
|
|
|
def failLabel = id.name + " " + id.version
|
|
|
|
|
|
|
|
|
|
lazy val mainClass: Class[T] forSome { type T <: xsbti.AppMain } =
|
2009-08-21 14:12:43 +02:00
|
|
|
{
|
2009-09-26 08:18:04 +02:00
|
|
|
val c = Class.forName(id.mainClass, true, loader)
|
|
|
|
|
c.asSubclass(classOf[xsbti.AppMain])
|
2009-08-21 14:12:43 +02:00
|
|
|
}
|
2009-09-26 08:18:04 +02:00
|
|
|
def newMain(): xsbti.AppMain = mainClass.newInstance
|
|
|
|
|
|
2009-09-27 20:39:26 +02:00
|
|
|
lazy val components = new ComponentProvider(appHome)
|
2009-08-21 14:12:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
2009-09-27 20:39:26 +02:00
|
|
|
}
|
|
|
|
|
class ComponentProvider(baseDirectory: File) extends xsbti.ComponentProvider
|
|
|
|
|
{
|
|
|
|
|
def componentLocation(id: String): File = new File(baseDirectory, id)
|
|
|
|
|
def component(id: String) = GetJars.wrapNull(componentLocation(id).listFiles).filter(_.isFile)
|
|
|
|
|
def defineComponent(id: String, files: Array[File]) =
|
|
|
|
|
{
|
|
|
|
|
val location = componentLocation(id)
|
|
|
|
|
if(location.exists)
|
|
|
|
|
throw new BootException("Cannot redefine component. ID: " + id + ", files: " + files.mkString(","))
|
|
|
|
|
else
|
2009-10-18 04:40:02 +02:00
|
|
|
Copy(files.toList, location)
|
2009-09-27 20:39:26 +02:00
|
|
|
}
|
2009-10-15 00:05:53 +02:00
|
|
|
def lockFile = ComponentProvider.lockFile(baseDirectory)
|
|
|
|
|
}
|
|
|
|
|
object ComponentProvider
|
|
|
|
|
{
|
|
|
|
|
def lockFile(baseDirectory: File) =
|
2009-10-11 04:01:03 +02:00
|
|
|
{
|
|
|
|
|
baseDirectory.mkdirs()
|
|
|
|
|
new File(baseDirectory, "sbt.components.lock")
|
|
|
|
|
}
|
2009-10-16 00:10:11 +02:00
|
|
|
}
|