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 + -
显示快捷键?