summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/util
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2014-10-04 12:33:11 -0700
committerSom Snytt <som.snytt@gmail.com>2014-10-06 08:00:22 -0700
commit964a197cd90e561d05c9d725cc13895f18b6a6d0 (patch)
tree51a80e3c486ad12b6b4f97920c696bdf167d54b4 /src/reflect/scala/reflect/internal/util
parent7b2c3cb8bb0f5f96f3182f551eb82cb1c59d460c (diff)
downloadscala-964a197cd90e561d05c9d725cc13895f18b6a6d0.tar.gz
scala-964a197cd90e561d05c9d725cc13895f18b6a6d0.tar.bz2
scala-964a197cd90e561d05c9d725cc13895f18b6a6d0.zip
SI-8843 AbsFileCL acts like a CL
Let the AbstractFileClassLoader override just the usual suspects. Normal delegation behavior should ensue. That's instead of overriding `getResourceAsStream`, which was intended that "The repl classloader now works more like you'd expect a classloader to." (Workaround for "Don't know how to construct an URL for something which exists only in memory.") Also override `findResources` so that `getResources` does the obvious thing, namely, return one iff `getResource` does. The translating class loader for REPL only special-cases `foo.class`: as a fallback, take `foo` as `$line42.$read$something$foo` and try that class file. That's the use case for "works like you'd expect it to." There was a previous fix to ensure `getResource` doesn't take a class name. The convenience behavior, that `classBytes` takes either a class name or a resource path ending in ".class", has been promoted to `ScalaClassLoader`.
Diffstat (limited to 'src/reflect/scala/reflect/internal/util')
-rw-r--r--src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala66
-rw-r--r--src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala6
2 files changed, 31 insertions, 41 deletions
diff --git a/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala b/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala
index 10a8b4c812..30dcbc21ca 100644
--- a/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala
+++ b/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala
@@ -5,16 +5,16 @@
package scala
package reflect.internal.util
-import scala.reflect.io.AbstractFile
+import scala.collection.{ mutable, immutable }
+import scala.reflect.io.{ AbstractFile, Streamable }
+import java.net.{ URL, URLConnection, URLStreamHandler }
import java.security.cert.Certificate
import java.security.{ ProtectionDomain, CodeSource }
-import java.net.{ URL, URLConnection, URLStreamHandler }
-import scala.collection.{ mutable, immutable }
+import java.util.{ Collections => JCollections, Enumeration => JEnumeration }
-/**
- * A class loader that loads files from a {@link scala.tools.nsc.io.AbstractFile}.
+/** A class loader that loads files from a {@link scala.tools.nsc.io.AbstractFile}.
*
- * @author Lex Spoon
+ * @author Lex Spoon
*/
class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
extends ClassLoader(parent)
@@ -22,7 +22,7 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
{
protected def classNameToPath(name: String): String =
if (name endsWith ".class") name
- else name.replace('.', '/') + ".class"
+ else s"${name.replace('.', '/')}.class"
protected def findAbstractFile(name: String): AbstractFile = {
var file: AbstractFile = root
@@ -56,35 +56,25 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
file
}
- // parent delegation in JCL uses getResource; so either add parent.getResAsStream
- // or implement findResource, which we do here as a study in scarlet (my complexion
- // after looking at CLs and URLs)
- override def findResource(name: String): URL = findAbstractFile(name) match {
+ override protected def findClass(name: String): Class[_] = {
+ val bytes = classBytes(name)
+ if (bytes.length == 0)
+ throw new ClassNotFoundException(name)
+ else
+ defineClass(name, bytes, 0, bytes.length, protectionDomain)
+ }
+ override protected def findResource(name: String): URL = findAbstractFile(name) match {
case null => null
- case file => new URL(null, "repldir:" + file.path, new URLStreamHandler {
+ case file => new URL(null, s"memory:${file.path}", new URLStreamHandler {
override def openConnection(url: URL): URLConnection = new URLConnection(url) {
- override def connect() { }
+ override def connect() = ()
override def getInputStream = file.input
}
})
}
-
- // this inverts delegation order: super.getResAsStr calls parent.getRes if we fail
- override def getResourceAsStream(name: String) = findAbstractFile(name) match {
- case null => super.getResourceAsStream(name)
- case file => file.input
- }
- // ScalaClassLoader.classBytes uses getResAsStream, so we'll try again before delegating
- override def classBytes(name: String): Array[Byte] = findAbstractFile(classNameToPath(name)) match {
- case null => super.classBytes(name)
- case file => file.toByteArray
- }
- override def findClass(name: String): Class[_] = {
- val bytes = classBytes(name)
- if (bytes.length == 0)
- throw new ClassNotFoundException(name)
- else
- defineClass(name, bytes, 0, bytes.length, protectionDomain)
+ override protected def findResources(name: String): JEnumeration[URL] = findResource(name) match {
+ case null => JCollections.enumeration(JCollections.emptyList[URL]) //JCollections.emptyEnumeration[URL]
+ case url => JCollections.enumeration(JCollections.singleton(url))
}
lazy val protectionDomain = {
@@ -106,15 +96,13 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
throw new UnsupportedOperationException()
}
- override def getPackage(name: String): Package = {
- findAbstractDir(name) match {
- case null => super.getPackage(name)
- case file => packages.getOrElseUpdate(name, {
- val ctor = classOf[Package].getDeclaredConstructor(classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[URL], classOf[ClassLoader])
- ctor.setAccessible(true)
- ctor.newInstance(name, null, null, null, null, null, null, null, this)
- })
- }
+ override def getPackage(name: String): Package = findAbstractDir(name) match {
+ case null => super.getPackage(name)
+ case file => packages.getOrElseUpdate(name, {
+ val ctor = classOf[Package].getDeclaredConstructor(classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[URL], classOf[ClassLoader])
+ ctor.setAccessible(true)
+ ctor.newInstance(name, null, null, null, null, null, null, null, this)
+ })
}
override def getPackages(): Array[Package] =
diff --git a/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala b/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala
index 63ea6e2c49..41011f6c6b 100644
--- a/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala
+++ b/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala
@@ -53,8 +53,10 @@ trait ScalaClassLoader extends JClassLoader {
}
/** An InputStream representing the given class name, or null if not found. */
- def classAsStream(className: String) =
- getResourceAsStream(className.replaceAll("""\.""", "/") + ".class")
+ def classAsStream(className: String) = getResourceAsStream {
+ if (className endsWith ".class") className
+ else s"${className.replace('.', '/')}.class" // classNameToPath
+ }
/** Run the main method of a class to be loaded by this classloader */
def run(objectName: String, arguments: Seq[String]) {