Skip to content

Commit

Permalink
SbtRunner now uses the project VM location to launch Java
Browse files Browse the repository at this point in the history
Added code that uses the VM location of the console's project for
launching Java. The code uses OS detection so let me know if it doesn't
work on your system.
  • Loading branch information
Sandro Gržičić committed Aug 17, 2012
1 parent d5dc16d commit 307a42d
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import scala.tools.eclipse.util.SWTUtils
import org.eclipse.core.resources.IProject
import org.eclipse.jface.dialogs.MessageDialog
import scala.tools.eclipse.sbtconsole.SbtRunner._
import org.eclipse.jdt.core.JavaCore

/**
* Entry point to the SBT Console.
Expand Down Expand Up @@ -85,7 +86,7 @@ class SbtBuilder(project: IProject) extends HasLogger {
import Preferences._

if (!projectDir.isEmpty && !sbtProcessStarted) {
val sbtConfig = SbtConfiguration(project, sbtPath(project), sbtJavaArgs(project), projectDir)
val sbtConfig = SbtConfiguration(JavaCore.create(project), sbtPath(project), sbtJavaArgs(project), projectDir)
val streams = ConsoleStreams(console.processInput, console.processOutput)
sbtRunner ! Start(sbtConfig, streams)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import scala.tools.eclipse.ScalaPlugin
import scala.concurrent.SyncVar
import java.io.FilterInputStream
import java.io.Closeable
import org.eclipse.jdt.launching.JavaRuntime
import org.eclipse.jdt.core.IJavaProject

object SbtRunner {
sealed trait SbtRunnerMessage
Expand All @@ -23,7 +25,7 @@ object SbtRunner {

case object Shutdown extends SbtRunnerMessage

case class SbtConfiguration(project: IProject, pathToSbt: String, sbtJavaArgs: String, projectDir: String)
case class SbtConfiguration(project: IJavaProject, pathToSbt: String, sbtJavaArgs: String, projectDir: String)
case class ConsoleStreams(in: InputStream, out: OutputStream)

/** Time the SBT process has to stop and clean up after receiving the "exit" command. */
Expand Down Expand Up @@ -83,7 +85,19 @@ class SbtRunner extends Actor with HasLogger {
)

try {
val javaCmd = "java" :: config.sbtJavaArgs.split(' ').map(_.trim).toList :::
// get Java binary location for the current platform
val javaLocation = for {
vmInstall <- Option(JavaRuntime.getVMInstall(config.project))
vmInstallLocation <- Option(vmInstall.getInstallLocation)
binary <- SbtUtils.getJavaBinary(vmInstallLocation)
} yield binary

if (javaLocation.isEmpty) {
eclipseLog.error("Error launching SBT: Cannot find a valid Java Runtime Environment binary.")
return
}

val javaCmd = javaLocation.get.toString :: config.sbtJavaArgs.split(' ').map(_.trim).toList :::
List("-jar", "-Dsbt.log.noformat=true", "-Djline.WindowsTerminal.directConsole=false", config.pathToSbt)
logger.info("Starting SBT in %s (%s)".format(config.projectDir, javaCmd))
val builder = Process(javaCmd.toArray, Some(new File(config.projectDir)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ object SbtUtils {
val USER_HOME = System.getProperty("user.home") + SEPARATOR
val SBT_PROJECT_FOLDER = "project/"
val SBT_LAUNCH_JAR = "sbt-launch.jar"

private var sbtClasspaths = Map.empty[String, List[IClasspathEntry]]

/**
* Returns the SBT path, SBT version and SBT Scala version.
* Returns the SBT path, SBT version and SBT Scala version.
* Uses empty strings in case of unknown information or exceptions.
* Use the specific methods in order to get specific information.
*/
def getSbtInfo(): SbtInfo = {
val path = getSbtPath()
val version = path map getSbtVersion getOrElse Left() fold(_ => "", identity)
val version = path map getSbtVersion getOrElse Left() fold (_ => "", identity)
val scalaVersion = sbtToScalaVersion(version)

SbtInfo(path getOrElse "", version, scalaVersion)
}

Expand All @@ -49,40 +49,40 @@ object SbtUtils {
jar.close()
}
}

/** Maps SBT versions to Scala versions. */
def sbtToScalaVersion(sbtVersion: String): String = sbtVersion match {
case "0.11.2" => "2.9.1"
case "0.11.3" => "2.9.2"
case s if s.isEmpty => ""
case _ => "2.9.2"
case _ => "2.9.2"
}

def getSbtClasspathFor(sbtVersion: String): List[IClasspathEntry] = {
if (!sbtClasspaths.contains(sbtVersion)) {
val scalaPath = "scala-" + sbtToScalaVersion(sbtVersion)

val scalaPath = "scala-" + sbtToScalaVersion(sbtVersion)
val sbtClasspath =
USER_HOME +
SBT_LIBRARY_LOCATION_PREFIX + scalaPath + SEPARATOR +
SBT_LIBRARY_LOCATION_SUFFIX + sbtVersion + SEPARATOR
SBT_LIBRARY_LOCATION_PREFIX + scalaPath + SEPARATOR +
SBT_LIBRARY_LOCATION_SUFFIX + sbtVersion + SEPARATOR

val classpath = MutableList.empty[IClasspathEntry]

val dir = new File(sbtClasspath)
val jars = dir.list(new FilenameFilter() {
def accept(dir: File, name: String) = name.endsWith(".jar")
})
jars foreach { jar =>
classpath += JavaCore.newLibraryEntry(new Path(sbtClasspath + jar), null, null)
}
classpath += JavaCore.newLibraryEntry(new Path(sbtClasspath + jar), null, null)
}

sbtClasspaths += sbtVersion -> classpath.toList
}

sbtClasspaths(sbtVersion)
}

/** Tries to find the SBT location based on the user's OS. */
def getSbtPath(): Option[String] = {
sys.props("os.name") match {
Expand All @@ -95,19 +95,36 @@ object SbtUtils {
if (sys.env.contains("ProgramFiles(x86)"))
possibleLocations :+= new File(sys.env("ProgramFiles(x86)") + SEPARATOR + "sbt" + SEPARATOR + SBT_LAUNCH_JAR)
} else {
// linux / mac, most likely
// linux / mac
possibleLocations :+= new File("~" + SEPARATOR + "bin" + SEPARATOR + SBT_LAUNCH_JAR)
possibleLocations :+= new File("~" + SEPARATOR + "bin" + SEPARATOR + "sbt" + SEPARATOR + SBT_LAUNCH_JAR)
}

possibleLocations foreach { file =>
if (file.exists())
return Some(file.toString)
}

case _ =>
}

None
}

/** Returns the JRE binary for the current system, given a valid Java VM location. */
def getJavaBinary(vmRoot: File): Option[File] = {
val vmPath = vmRoot.toString
sys.props("os.name") match {
case os: String =>
val binaryName = if (os.toLowerCase.contains("windows")) {
// windows
"java.exe"
} else {
// linux / mac
"java"
}
Some(new File(vmRoot.toString + SEPARATOR + "bin" + SEPARATOR + binaryName))
case _ => None
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class ShellConsoleKeyListener(console: ShellConsole, page: ShellConsolePage)
processWriter.flush()

// wait for the process to print out the completion (TODO: optimize somehow?)
// because it's not possible to find out the end of the completion
Thread.sleep(100)

val contentBuffer = transferThread.contentBuffer.toString()
Expand Down

0 comments on commit 307a42d

Please sign in to comment.