summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorJosh Suereth <joshua.suereth@gmail.com>2011-08-29 20:24:39 +0000
committerJosh Suereth <joshua.suereth@gmail.com>2011-08-29 20:24:39 +0000
commit8f3c3f5387125fe43ef2f7cc63f410413fa51365 (patch)
treea4b877a7efe921f7834ef8e5bd54d4dd2ca825be /src/compiler
parentd52e53ce4ff8ab2eb26eba794a637b43487f3608 (diff)
downloadscala-8f3c3f5387125fe43ef2f7cc63f410413fa51365.tar.gz
scala-8f3c3f5387125fe43ef2f7cc63f410413fa51365.tar.bz2
scala-8f3c3f5387125fe43ef2f7cc63f410413fa51365.zip
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
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/ant/ClassloadVerify.scala53
-rw-r--r--src/compiler/scala/tools/ant/antlib.xml2
-rw-r--r--src/compiler/scala/tools/util/VerifyClass.scala52
3 files changed, 107 insertions, 0 deletions
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 @@
<antlib>
<!--<taskdef name="scala"
classname="scala.tools.ant.Scala"/>-->
+ <taskdef name="classloadVerify"
+ classname="scala.tools.ant.ClassloadVerify"/>
<taskdef name="fsc"
classname="scala.tools.ant.FastScalac"/>
<taskdef name="scalac"
diff --git a/src/compiler/scala/tools/util/VerifyClass.scala b/src/compiler/scala/tools/util/VerifyClass.scala
new file mode 100644
index 0000000000..5f636f63fb
--- /dev/null
+++ b/src/compiler/scala/tools/util/VerifyClass.scala
@@ -0,0 +1,52 @@
+package scala.tools.util
+
+import scala.tools.nsc.io._
+import java.net.URLClassLoader
+import collection.JavaConverters._
+
+
+object VerifyClass {
+
+ // Returns the error if there's a failure
+ private def checkClass(name : String, cl: ClassLoader) : (String, Option[String]) = {
+ try {
+ Class.forName(name, true, cl)
+ (name, None)
+ } catch {
+ case x => (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)
+ }
+}