Merge pull request #2214 from twitter-forks/stuhood/more-thorough-classfile-location-detection

More thorough classfile location detection
This commit is contained in:
eugene yokota 2015-09-28 23:17:48 -04:00
commit 33478132c5
9 changed files with 41 additions and 7 deletions

View File

@ -160,7 +160,7 @@ object ClassToAPI {
} catch {
case e: Throwable =>
throw new IllegalStateException(
s"Failed to parse class $c: this may mean your classfiles are corrupted. Please clean and try again.",
s"Failed to parse $c: this may mean your classfiles are corrupted. Please clean and try again.",
e
)
}

View File

@ -38,14 +38,23 @@ object IO {
/**
* Returns a URL for the directory or jar containing the the class file `cl`.
* If the location cannot be determined, an error is generated.
* Note that Java standard library classes typically do not have a location associated with them.
*/
def classLocation(cl: Class[_]): URL =
{
val codeSource = cl.getProtectionDomain.getCodeSource
if (codeSource == null) sys.error("No class location for " + cl)
else codeSource.getLocation
def classLocation(cl: Class[_]): URL = {
val codeSource = cl.getProtectionDomain.getCodeSource
if (codeSource ne null) {
codeSource.getLocation
} else {
// NB: This assumes that classes without code sources are System classes, and thus located in
// jars. It assumes that `urlAsFile` will truncate to the containing jar file.
val clsfile = s"${cl.getName.replace('.', '/')}.class"
Option(ClassLoader.getSystemClassLoader.getResource(clsfile))
.flatMap {
urlAsFile
}.getOrElse {
sys.error("No class location for " + cl)
}.toURI.toURL
}
}
/**
* Returns the directory or jar file containing the the class file `cl`.

View File

@ -0,0 +1,25 @@
package sbt
import util.Try
import org.scalacheck._
import Prop._
object IOSpecification extends Properties("IO") {
property("classLocation able to determine containing directories") =
Prop.forAll(classes) { (c: Class[_]) =>
Try(IO.classLocationFile(c)).toOption.exists {
case jar if jar.getName.endsWith(".jar") => jar.isFile
case dir => dir.isDirectory
}
}
implicit def classes: Gen[Class[_]] =
Gen.oneOf(
this.getClass,
classOf[java.lang.Integer],
classOf[String],
classOf[Thread],
classOf[Properties]
)
}