From 8f3c3f5387125fe43ef2f7cc63f410413fa51365 Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Mon, 29 Aug 2011 20:24:39 +0000 Subject: Added extraneous test where classes are verifie... Added extraneous test where classes are verified by loading them in non-boot classloaders one at a time. These are not wired into the standard workflow, but available optionally. Review by rytz --- src/compiler/scala/tools/ant/ClassloadVerify.scala | 53 ++++++++++++++++++++++ src/compiler/scala/tools/ant/antlib.xml | 2 + src/compiler/scala/tools/util/VerifyClass.scala | 52 +++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 src/compiler/scala/tools/ant/ClassloadVerify.scala create mode 100644 src/compiler/scala/tools/util/VerifyClass.scala (limited to 'src') diff --git a/src/compiler/scala/tools/ant/ClassloadVerify.scala b/src/compiler/scala/tools/ant/ClassloadVerify.scala new file mode 100644 index 0000000000..33a20f6894 --- /dev/null +++ b/src/compiler/scala/tools/ant/ClassloadVerify.scala @@ -0,0 +1,53 @@ +/* __ *\ +** ________ ___ / / ___ Scala Ant Tasks ** +** / __/ __// _ | / / / _ | (c) 2005-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.tools.ant + +import org.apache.tools.ant.Project +import org.apache.tools.ant.types.{Path, Reference} +import collection.JavaConverters._ +import scala.tools.util.VerifyClass + +class ClassloadVerify extends ScalaMatchingTask { + + /** The class path to use for this compilation. */ + protected var classpath: Option[Path] = None + + /** Sets the `classpath` attribute. Used by [[http://ant.apache.org Ant]]. + * @param input The value of `classpath`. */ + def setClasspath(input: Path) { + classpath = Some(input) + } + + def setClasspathref(input: Reference) { + val p = new Path(getProject()) + p.setRefid(input) + classpath = Some(p) + } + + private def getClasspath: Array[String] = classpath match { + case None => buildError("Member 'classpath' is empty.") + case Some(x) => x.list.toArray + } + + override def execute(): Unit = { + val results = VerifyClass.run(getClasspath).asScala + results foreach (r => log("Checking: " + r, Project.MSG_DEBUG)) + val errors = for((name, error) <- results; if error != null) yield (name,error) + if(errors.isEmpty) { + // TODO - Log success + log("Classload verification succeeded with " + results.size + " classes.", Project.MSG_INFO) + } else { + for((name, error) <- errors) { + log(name + " failed verification with: " + error, Project.MSG_ERR) + } + buildError(errors.size + " classload verification errors on " + results.size + " classes.") + } + } + +} diff --git a/src/compiler/scala/tools/ant/antlib.xml b/src/compiler/scala/tools/ant/antlib.xml index 06a355d21d..bbdf1fc9db 100644 --- a/src/compiler/scala/tools/ant/antlib.xml +++ b/src/compiler/scala/tools/ant/antlib.xml @@ -1,6 +1,8 @@ + (name, Some(x.toString)) + } + } + + def checkClassesInJar(name: String, cl: ClassLoader) = new Jar(File(name)) filter (_.getName.endsWith(".class")) map { x => + checkClass(x.getName.stripSuffix(".class").replace('/', '.'), cl) + } toMap + + def checkClassesInDir(name: String, cl: ClassLoader) = (for { + file <- Path(name).walk + if file.name endsWith ".class" + } yield checkClass(name, cl)) toMap + + def checkClasses(name: String, cl: ClassLoader) = + if (name endsWith ".jar") checkClassesInJar(name, cl) + else checkClassesInDir(name, cl) + + /** Attempts to load all classes on the classpath defined in the args string array. This method is meant to be used via reflection from tools like SBT or Ant. */ + def run(args: Array[String]): java.util.Map[String, String] = { + val urls = args.map(Path.apply).map(_.toFile.toURI.toURL).toArray + println("As urls: " + urls.mkString(",")) + val cl = URLClassLoader.newInstance(urls, null) + val results = args.flatMap(n => checkClasses(n, cl)).toMap + (for { (name, result) <- results } yield (name, result.getOrElse(null))).asJava + } + + + def main(args: Array[String]): Unit = { + val results = run(args).asScala + println("Processed " + results.size + " classes.") + val errors = results.filter(_._2 != null) + for( (name, result) <- results; if result != null) { + println(name + " had error: " + result) + } + System.exit(if(errors.size > 0) 1 else 0) + } +} -- cgit v1.2.3