aboutsummaryrefslogtreecommitdiff
path: root/libraries/eval
diff options
context:
space:
mode:
authormmcbride <mccv@twitter.com>2011-10-26 14:26:58 -0700
committerChristopher Vogt <oss.nsp@cvogt.org>2016-11-07 02:08:38 -0500
commitdeadedb9bcb21d49b49a84987deda66868c110b8 (patch)
treedcbb579adc900fa96d4366435d18ab9b2e3272a1 /libraries/eval
parentde4f870d5ad294408b6fa97a3a6ff1d02a4273b8 (diff)
downloadcbt-deadedb9bcb21d49b49a84987deda66868c110b8.tar.gz
cbt-deadedb9bcb21d49b49a84987deda66868c110b8.tar.bz2
cbt-deadedb9bcb21d49b49a84987deda66868c110b8.zip
[split] Fixing eval precompile issues with invalid characters in classnames. Also, git-review bump
Diffstat (limited to 'libraries/eval')
-rw-r--r--libraries/eval/Eval.scala31
-rw-r--r--libraries/eval/test/EvalTest.scala37
-rw-r--r--libraries/eval/test/resources/file-with-dash.scala1
3 files changed, 65 insertions, 4 deletions
diff --git a/libraries/eval/Eval.scala b/libraries/eval/Eval.scala
index b9d225a..d353338 100644
--- a/libraries/eval/Eval.scala
+++ b/libraries/eval/Eval.scala
@@ -17,6 +17,7 @@
package com.twitter.util
import com.twitter.io.StreamIO
+import com.twitter.conversions.string._
import java.io.{File, InputStream, FileInputStream, FileNotFoundException}
import java.math.BigInteger
import java.net.URLClassLoader
@@ -30,6 +31,7 @@ import scala.tools.nsc.interpreter.AbstractFileClassLoader
import scala.tools.nsc.io.{AbstractFile, VirtualDirectory}
import scala.tools.nsc.reporters.AbstractReporter
import scala.tools.nsc.util.{BatchSourceFile, Position}
+import scala.util.matching.Regex
case class LastMod(timestamp: Option[Long], code: String)
@@ -39,6 +41,7 @@ case class LastMod(timestamp: Option[Long], code: String)
@deprecated("use a throw-away instance of Eval instead")
object Eval extends Eval {
private val jvmId = java.lang.Math.abs(new Random().nextInt())
+ val classCleaner: Regex = "\\W".r
}
/**
@@ -159,7 +162,14 @@ class Eval(target: Option[File]) {
case None => compiler.reset()
}
- val className = "Evaluator__" + files(0).getName.split("\\.")(0)
+ // why all this nonsense? Well.
+ // 1) We want to know which file the eval'd code came from
+ // 2) But sometimes files have characters that aren't valid in Java/Scala identifiers
+ // 3) And sometimes files with the same name live in different subdirectories
+ // so, clean it hash it and slap it on the end of Evaluator
+ val cleanBaseName = fileToClassName(files(0))
+ val className = "Evaluator__%s_%s".format(
+ cleanBaseName, uniqueId(files(0).getCanonicalPath, None))
applyProcessed(className, processed.code, false)
} else {
apply(files.map { scala.io.Source.fromFile(_).mkString }.mkString("\n"), true)
@@ -255,10 +265,25 @@ class Eval(target: Option[File]) {
compiler.findClass(className).getOrElse { throw new ClassNotFoundException("no such class: " + className) }
}
- private def uniqueId(code: String): String = {
+ private[util] def uniqueId(code: String, idOpt: Option[Int] = Some(jvmId)): String = {
val digest = MessageDigest.getInstance("SHA-1").digest(code.getBytes())
val sha = new BigInteger(1, digest).toString(16)
- sha + "_" + jvmId
+ idOpt match {
+ case Some(id) => sha + "_" + jvmId
+ case _ => sha
+ }
+ }
+
+ private[util] def fileToClassName(f: File): String = {
+ // HOPE YOU'RE HAPPY GUYS!!!!
+ val fileName = f.getName
+ val baseName = fileName.lastIndexOf('.') match {
+ case -1 => fileName
+ case dot => fileName.substring(0, dot)
+ }
+ baseName.regexSub(Eval.classCleaner) { m =>
+ "$%02x".format(m.group(0).charAt(0).toInt)
+ }
}
/*
diff --git a/libraries/eval/test/EvalTest.scala b/libraries/eval/test/EvalTest.scala
index 40d15a7..32855de 100644
--- a/libraries/eval/test/EvalTest.scala
+++ b/libraries/eval/test/EvalTest.scala
@@ -7,6 +7,7 @@ import com.twitter.io.TempFile
object EvalSpec extends Specification {
"Evaluator" should {
+
"apply('expression')" in {
(new Eval).apply[Int]("1 + 1") mustEqual 2
}
@@ -22,6 +23,23 @@ object EvalSpec extends Specification {
derived() mustEqual "hello"
}
+ "apply(new File(...) with a dash in the name with target" in {
+ val f = File.createTempFile("eval", "target")
+ f.delete()
+ f.mkdir()
+ val e = new Eval(Some(f))
+ val sourceFile = TempFile.fromResourcePath("/file-with-dash.scala")
+ val res: String = e(sourceFile)
+ res mustEqual "hello"
+ val className = e.fileToClassName(sourceFile)
+ val fullClassName = "Evaluator__%s_%s.class".format(
+ className, e.uniqueId(sourceFile.getCanonicalPath, None))
+ val targetFileName = f.getAbsolutePath() + File.separator + fullClassName
+ val targetFile = new File(targetFileName)
+ targetFile.exists must be_==(true)
+ val targetMod = targetFile.lastModified
+ }
+
"apply(new File(...) with target" in {
val f = File.createTempFile("eval", "target")
f.delete()
@@ -32,7 +50,10 @@ object EvalSpec extends Specification {
res mustEqual 2
// make sure it created a class file with the expected name
- val targetFileName = f.getAbsolutePath() + File.separator + "Evaluator__" + sourceFile.getName + ".class"
+ val className = e.fileToClassName(sourceFile)
+ val fullClassName = "Evaluator__%s_%s.class".format(
+ className, e.uniqueId(sourceFile.getCanonicalPath, None))
+ val targetFileName = f.getAbsolutePath() + File.separator + fullClassName
val targetFile = new File(targetFileName)
targetFile.exists must be_==(true)
val targetMod = targetFile.lastModified
@@ -103,5 +124,19 @@ object EvalSpec extends Specification {
Eval[() => String](
TempFile.fromResourcePath("RubyInclude.scala")) must throwA[Throwable]
}
+
+ "clean class names" in {
+ val e = new Eval()
+ // regular old scala file
+ e.fileToClassName(new File("foo.scala")) mustEqual "foo"
+ // without an extension
+ e.fileToClassName(new File("foo")) mustEqual "foo"
+ // with lots o dots
+ e.fileToClassName(new File("foo.bar.baz")) mustEqual "foo$2ebar"
+ // with dashes
+ e.fileToClassName(new File("foo-bar-baz.scala")) mustEqual "foo$2dbar$2dbaz"
+ // with crazy things
+ e.fileToClassName(new File("foo$! -@@@")) mustEqual "foo$24$21$20$2d$40$40$40"
+ }
}
}
diff --git a/libraries/eval/test/resources/file-with-dash.scala b/libraries/eval/test/resources/file-with-dash.scala
new file mode 100644
index 0000000..3580093
--- /dev/null
+++ b/libraries/eval/test/resources/file-with-dash.scala
@@ -0,0 +1 @@
+"hello"