gatk-3.8/public/scala/src/org/broadinstitute/sting/queue/QScriptManager.scala

135 lines
4.7 KiB
Scala

package org.broadinstitute.sting.queue
import scala.tools.nsc.{Global, Settings}
import scala.tools.nsc.io.PlainFile
import org.broadinstitute.sting.queue.util.Logging
import collection.JavaConversions._
import java.io.File
import scala.tools.nsc.reporters.AbstractReporter
import java.lang.String
import org.apache.log4j.Level
import scala.tools.nsc.util.{FakePos, NoPosition, Position}
import org.broadinstitute.sting.queue.util.TextFormatUtils._
import org.broadinstitute.sting.utils.classloader.JVMUtils
/**
* Plugin manager for QScripts which loads QScripts into the current class loader.
*/
class QScriptManager() extends Logging {
/**
* Compiles and loads the scripts in the files into the current classloader.
* Heavily based on scala/src/compiler/scala/tools/ant/Scalac.scala
*/
def loadScripts(scripts: List[File], tempDir: File) {
if (scripts.size > 0) {
val settings = new Settings((error: String) => logger.error(error))
settings.deprecation.value = true
settings.outdir.value = tempDir.getPath
// Set the classpath to the current class path.
JVMUtils.getClasspathURLs.foreach(url => settings.classpath.append(url.getPath))
val reporter = new QScriptManager.Log4JReporter(settings)
val compiler = new Global(settings, reporter)
val run = new compiler.Run
logger.info("Compiling %s QScript%s".format(scripts.size, plural(scripts.size)))
logger.debug("Compilation directory: " + settings.outdir.value)
run.compileFiles(scripts.map(new PlainFile(_)))
reporter.printSummary()
if (reporter.hasErrors) {
val msg = "Compile of %s failed with %d error%s".format(
scripts.mkString(", "), reporter.ERROR.count, plural(reporter.ERROR.count))
throw new QException(msg)
}
else if (reporter.WARNING.count > 0)
logger.warn("Compile succeeded with %d warning%s".format(
reporter.WARNING.count, plural(reporter.WARNING.count)))
else
logger.info("Compilation complete")
}
}
}
/**
* Plugin manager for QScripts which loads QScripts into the current classloader.
*/
object QScriptManager extends Logging {
/**
* NSC (New Scala Compiler) reporter which logs to Log4J.
* Heavily based on scala/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
*/
private class Log4JReporter(val settings: Settings) extends AbstractReporter {
def displayPrompt { throw new UnsupportedOperationException("Unable to prompt the user. Prompting should be off.") }
/**
* Displays the message at position with severity.
* @param posIn Position of the event in the file that generated the message.
* @param msg Message to display.
* @param severity Severity of the event.
*/
def display(posIn: Position, msg: String, severity: Severity) {
severity.count += 1
val level = severity match {
case INFO => Level.INFO
case WARNING => Level.WARN
case ERROR => Level.ERROR
}
val pos = if (posIn eq null) NoPosition
else if (posIn.isDefined) posIn.inUltimateSource(posIn.source)
else posIn
pos match {
case FakePos(fmsg) =>
printMessage(level, fmsg+" "+msg)
case NoPosition =>
printMessage(level, msg)
case _ =>
val file = pos.source.file
printMessage(level, file.name+":"+pos.line+": "+msg)
printSourceLine(level, pos)
}
}
/**
* Prints a summary count of warnings and errors.
*/
def printSummary() {
if (WARNING.count > 0)
printMessage(Level.WARN, countElementsAsString(WARNING.count, "warning") + " found")
if (ERROR.count > 0)
printMessage(Level.ERROR, countElementsAsString(ERROR.count, "error") + " found")
}
/**
* Prints the source code line of an event followed by a pointer within the line to the error.
* @param level Severity level.
* @param pos Position in the file of the event.
*/
private def printSourceLine(level: Level, pos: Position) {
printMessage(level, pos.lineContent.stripLineEnd)
printColumnMarker(level, pos)
}
/**
* Prints the column marker of the given position.
* @param level Severity level.
* @param pos Position in the file of the event.
*/
private def printColumnMarker(level: Level, pos: Position) {
if (pos.isDefined) { printMessage(level, " " * (pos.column - 1) + "^") }
}
/**
* Prints the message at the severity level.
* @param level Severity level.
* @param message Message content.
*/
private def printMessage(level: Level, message: String) {
logger.log(level, message)
}
}
}