plugin.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 153 行

SCALA
153
字号
/* NSC -- new Scala compiler * Copyright 2007-2008 LAMP/EPFL * @author Lex Spoon */// $Id: Plugin.scala 14416 2008-03-19 01:17:25Z mihaylov $package scala.tools.nsc.pluginsimport java.io.Fileimport java.net.URLClassLoaderimport java.util.jar.JarFileimport java.util.zip.ZipExceptionimport scala.collection.mutableimport mutable.ListBufferimport scala.xml.XML/** <p> *    Information about a plugin loaded from a jar file. *  </p> *  <p> *    The concrete subclass must have a one-argument constructor *    that accepts an instance of <code>Global</code>. *  </p><pre> *    (val global: Global) *  </pre> * *  @author Lex Spoon *  @version 1.0, 2007-5-21 */abstract class Plugin {  /** The name of this plugin */  val name: String  /** The components that this phase defines */  val components: List[PluginComponent]  /** A one-line description of the plugin */  val description: String  /** The compiler that this plugin uses.  This is normally equated   *  to a constructor parameter in the concrete subclass. */  val global: Global  /** Handle any plugin-specific options.  The -P:plugname: part   *  will not be present. */  def processOptions(options: List[String], error: String => Unit) {    if (!options.isEmpty)      error("Error: " + name + " has no options")  }  /** A description of this plugin's options, suitable as a response   *  to the -help command-line option.  Conventionally, the   *  options should be listed with the <code>-P:plugname:</code>   *  part included.   */  val optionsHelp: Option[String] = None}/** ... * *  @author Lex Spoon *  @version 1.0, 2007-5-21 */object Plugin {  /** Create a class loader with the specified file plus   *  the loader that loaded the Scala compiler.   */  private def loaderFor(jarfiles: Seq[File]): ClassLoader = {    val compilerLoader = classOf[Plugin].getClassLoader    val jarurls = jarfiles.map(_.toURL).toArray    new URLClassLoader(jarurls, compilerLoader)  }  /** Try to load a plugin description from the specified   *  file, returning None if it does not work. */  private def loadDescription(jarfile: File): Option[PluginDescription] = {    if (!jarfile.exists) return None    try {      val jar = new JarFile(jarfile)      try {	val ent = jar.getEntry("scalac-plugin.xml")	if(ent == null) return None	val inBytes = jar.getInputStream(ent)	val packXML = XML.load(inBytes)	inBytes.close()        	PluginDescription.fromXML(packXML)      } finally {	jar.close()      }    } catch {      case _:ZipException => None    }  }  type AnyClass = Class[_]  /** Loads a plugin class from the named jar file.  Returns None   *  if the jar file has no plugin in it or if the plugin   *  is badly formed.   */  def loadFrom(jarfile: File, loader: ClassLoader): Option[AnyClass] = {    val pluginInfo = loadDescription(jarfile).get    try {      Some(loader.loadClass(pluginInfo.classname))    } catch {      case _:ClassNotFoundException =>	println("Warning: class not found for plugin in " + jarfile +                " (" + pluginInfo.classname + ")")      None    }   }  /** Load all plugins found in the argument list, both in the   *  jar files explicitly listed, and in the jar files in the   *  directories specified. Skips all plugins in <code>ignoring</code>.   *  A single classloader is created and used to load all of them.   */  def loadAllFrom(jars: List[File], 		  dirs: List[File], 		  ignoring: List[String]): List[AnyClass] =   {    val alljars = new ListBuffer[File]    alljars ++= jars    for {      dir <- dirs if dir.isDirectory      entries = dir.listFiles      if entries ne null      entry <- entries.toList.sort((f1, f2) => f1.getName <= f2.getName)      if entry.toString.toLowerCase endsWith ".jar"      pdesc <- loadDescription(entry)      if !(ignoring contains pdesc.name)    } alljars += entry    val loader = loaderFor(alljars.toList)    alljars.toList.map(f => loadFrom(f,loader)).flatMap(x => x)  }  /** Instantiate a plugin class, given the class and   *  the compiler it is to be used in.   */  def instantiate(clazz: AnyClass, global: Global): Plugin = {    val constructor = clazz.getConstructor(Array(classOf[Global]))    constructor.newInstance(Array(global)).asInstanceOf[Plugin]  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?