import sbt._ import Build._ import Keys._ // This is helper code to validate that generated class files will succed in bytecode verification at class-load time. object VerifyClassLoad { lazy val checkClassLoad: TaskKey[Unit] = TaskKey("check-class-load", "checks whether or not the class files generated by scala are deemed acceptable by classloaders.") lazy val checkClassRunner: TaskKey[ClassVerifyRunner] = TaskKey("check-class-runner", "A wrapper around reflective calls to the VerifyClass class.") def settings: Seq[Setting[_]] = Seq( checkClassRunner <<= (fullClasspath in Runtime) map (cp => new ClassVerifyRunner(data(cp))), fullClasspath in checkClassLoad := Seq(), checkClassLoad <<= (checkClassRunner, fullClasspath in checkClassLoad, streams) map { (runner, dirs, s) => import collection.JavaConverters._ val results = runner.run(data(dirs).map(_.getAbsolutePath).toArray).asScala s.log.info("Processed " + results.size + " classes.") val errors = results.filter(_._2 != null) for( (name, result) <- results; if result != null) { s.log.error(name + " had error: " + result) } if(errors.size > 0) error("Classload validation errors encountered") () } ) // TODO - Use class ClassVerifyRunner(classpath: Seq[File]) { // Classloader that does *not* have this as parent, for differing Scala version. lazy val classLoader = new java.net.URLClassLoader(classpath.map(_.toURI.toURL).toArray, null) lazy val (mainClass, mainMethod) = try { val c = classLoader.loadClass("scala.tools.util.VerifyClass") val m = c.getMethod("run", classOf[Array[String]]) (c,m) } def run(args: Array[String]): java.util.Map[String,String] = try { mainMethod.invoke(null, args).asInstanceOf[java.util.Map[String,String]] } catch { case e => //error("Could not run Partest: " + e) throw e } } }