sbt/launch/Launch.scala

199 lines
8.7 KiB
Scala
Raw Normal View History

2010-02-08 05:45:19 +01:00
/* sbt -- Simple Build Tool
* Copyright 2008, 2009, 2010, 2011 Mark Harrah
2010-02-08 05:45:19 +01:00
*/
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._
import BootConfiguration.{CompilerModuleName, LibraryModuleName}
import java.io.File
import java.net.URL
import scala.collection.immutable.List
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
def apply(arguments: List[String]): Unit = apply( (new File("")).getAbsoluteFile , arguments )
2009-10-18 04:40:02 +02:00
def apply(currentDirectory: File, arguments: List[String]): Unit =
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 =
{
val config = Configuration.parse(configLocation, currentDirectory)
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
{
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)
initialized(currentDirectory, parsed, arguments)
}
2009-10-18 04:40:02 +02:00
def initialized(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Unit =
{
parsed.logging.debug("Parsed configuration: " + parsed)
val resolved = ResolveValues(parsed)
resolved.logging.debug("Resolved configuration: " + resolved)
2009-10-18 04:40:02 +02:00
explicit(currentDirectory, resolved, arguments)
}
2009-10-18 04:40:02 +02:00
def explicit(currentDirectory: File, explicit: LaunchConfiguration, arguments: List[String]): Unit =
launch( run(Launcher(explicit)) ) (
2009-10-18 04:40:02 +02:00
new RunConfiguration(explicit.getScalaVersion, explicit.app.toID, currentDirectory, arguments) )
def run(launcher: xsbti.Launcher)(config: RunConfiguration): xsbti.MainResult =
2009-08-21 14:12:43 +02:00
{
import config._
val scalaProvider: xsbti.ScalaProvider = launcher.getScala(scalaVersion, "(for " + app.name + ")")
2009-09-26 08:18:04 +02:00
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)
val main = appProvider.newMain()
try { main.run(appConfig) }
catch { case e: xsbti.FullReload => if(e.clean) delete(launcher.bootDirectory); throw e }
}
private[this] def delete(f: File)
{
if(f.isDirectory)
{
val fs = f.listFiles()
if(fs ne null) fs foreach delete
}
if(f.exists) f.delete()
}
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-09-26 08:18:04 +02:00
}
final class RunConfiguration(val scalaVersion: String, val app: xsbti.ApplicationID, val workingDirectory: File, val arguments: List[String])
2009-09-26 08:18:04 +02:00
import BootConfiguration.{appDirectoryName, baseDirectoryName, ScalaDirectoryName, TestLoadScalaClasses}
class Launch private[xsbt](val bootDirectory: File, val lockBoot: Boolean, val ivyOptions: IvyOptions) extends xsbti.Launcher
2009-09-26 08:18:04 +02:00
{
import ivyOptions.{classifiers, repositories}
bootDirectory.mkdirs
private val scalaProviders = new Cache[String, String, ScalaProvider](new ScalaProvider(_, _))
def getScala(version: String): xsbti.ScalaProvider = getScala(version, "")
def getScala(version: String, reason: String): xsbti.ScalaProvider = scalaProviders(version, reason)
2009-09-26 08:18:04 +02:00
2011-03-05 11:58:10 +01:00
lazy val topLoader = (new JNAProvider).loader
val updateLockFile = if(lockBoot) Some(new File(bootDirectory, "sbt.boot.lock")) else None
def globalLock: xsbti.GlobalLock = Locks
def ivyHome = ivyOptions.ivyHome.orNull
2011-07-20 03:29:05 +02:00
def ivyRepositories = repositories.toArray
2011-03-05 11:58:10 +01:00
class JNAProvider extends Provider
{
lazy val id = new Application("net.java.dev.jna", "jna", new Explicit("3.2.3"), "", Nil, false, array())
lazy val configuration = new UpdateConfiguration(bootDirectory, ivyOptions.ivyHome, "", repositories)
2011-03-05 11:58:10 +01:00
lazy val libDirectory = new File(bootDirectory, baseDirectoryName(""))
def baseDirectories: List[File] = new File(libDirectory, appDirectoryName(id.toID, File.separator)) :: Nil
def testLoadClasses: List[String] = "com.sun.jna.Function" :: Nil
def extraClasspath = array()
def target = new UpdateApp(id, Nil)
lazy val parentLoader = new BootFilteredLoader(getClass.getClassLoader)
def failLabel = "JNA"
def lockFile = updateLockFile
}
class ScalaProvider(val version: String, override val reason: 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
def parentLoader = topLoader
lazy val configuration = new UpdateConfiguration(bootDirectory, ivyOptions.ivyHome, 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)
2011-03-05 11:58:10 +01:00
def compilerJar = new File(scalaHome, CompilerModuleName + ".jar")
def libraryJar = new File(scalaHome, LibraryModuleName + ".jar")
2011-03-05 11:58:10 +01:00
override def classpath = Provider.getJars(scalaHome :: Nil)
2009-10-18 04:40:02 +02:00
def baseDirectories = List(scalaHome)
2009-09-26 08:18:04 +02:00
def testLoadClasses = TestLoadScalaClasses
def target = new UpdateScala(Value.get(classifiers.forScala))
2009-09-26 08:18:04 +02:00
def failLabel = "Scala " + version
def lockFile = updateLockFile
2010-02-05 00:56:07 +01:00
def extraClasspath = array()
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
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)
def target = new UpdateApp(Application(id), Value.get(classifiers.app))
2009-09-26 08:18:04 +02:00
def failLabel = id.name + " " + id.version
def lockFile = updateLockFile
2010-02-05 00:56:07 +01:00
def mainClasspath = fullClasspath
def extraClasspath = id.classpathExtra
2009-09-26 08:18:04 +02:00
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
lazy val components = new ComponentProvider(appHome, lockBoot)
2009-08-21 14:12:43 +02:00
}
}
}
object Launcher
{
2011-07-20 03:29:05 +02:00
def apply(bootDirectory: File, repositories: List[xsbti.Repository]): xsbti.Launcher =
apply(bootDirectory, IvyOptions(None, Classifiers(Nil, Nil), repositories))
def apply(bootDirectory: File, ivyOptions: IvyOptions): xsbti.Launcher =
apply(bootDirectory, ivyOptions, GetLocks.find)
def apply(bootDirectory: File, ivyOptions: IvyOptions, locks: xsbti.GlobalLock): xsbti.Launcher =
new Launch(bootDirectory, true, ivyOptions) {
override def globalLock = locks
}
def apply(explicit: LaunchConfiguration): xsbti.Launcher =
new Launch(explicit.boot.directory, explicit.boot.lock, explicit.ivyConfiguration)
def defaultAppProvider(baseDirectory: File): xsbti.AppProvider = getAppProvider(baseDirectory, Configuration.configurationOnClasspath)
def getAppProvider(baseDirectory: File, configLocation: URL): xsbti.AppProvider =
{
val parsed = ResolvePaths(Configuration.parse(configLocation, baseDirectory), baseDirectory)
Initialize.process(parsed.boot.properties, parsed.appProperties, Initialize.selectQuick)
val config = ResolveValues(parsed)
val launcher = apply(config)
val scalaProvider = launcher.getScala(config.getScalaVersion)
scalaProvider.app(config.app.toID)
}
}
class ComponentProvider(baseDirectory: File, lockBoot: Boolean) extends xsbti.ComponentProvider
{
def componentLocation(id: String): File = new File(baseDirectory, id)
def component(id: String) = Provider.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)
}
def addToComponent(id: String, files: Array[File]): Boolean =
Copy(files.toList, componentLocation(id))
def lockFile = if(lockBoot) ComponentProvider.lockFile(baseDirectory) else null // null for the Java interface
}
object ComponentProvider
{
def lockFile(baseDirectory: File) =
2009-10-11 04:01:03 +02:00
{
baseDirectory.mkdirs()
new File(baseDirectory, "sbt.components.lock")
}
}