summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-04-15 11:36:43 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-04-15 12:04:23 +0200
commit967ceb28ab2737ee16112b4c9be46419f43b9a99 (patch)
tree8ed0aa510de435e3f64316ea4cc1cb466d8c9f38 /src
parent364dd41c3e0e33afe6c3ec6e0c04f1d345c4b6ca (diff)
downloadscala-967ceb28ab2737ee16112b4c9be46419f43b9a99.tar.gz
scala-967ceb28ab2737ee16112b4c9be46419f43b9a99.tar.bz2
scala-967ceb28ab2737ee16112b4c9be46419f43b9a99.zip
big fat error message for default mirror failures
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/reflect/ReflectionUtils.scala22
-rw-r--r--src/library/scala/reflect/package.scala67
2 files changed, 83 insertions, 6 deletions
diff --git a/src/library/scala/reflect/ReflectionUtils.scala b/src/library/scala/reflect/ReflectionUtils.scala
index 1be46eac55..79a42f6ec4 100644
--- a/src/library/scala/reflect/ReflectionUtils.scala
+++ b/src/library/scala/reflect/ReflectionUtils.scala
@@ -27,6 +27,28 @@ object ReflectionUtils {
case ex if pf isDefinedAt unwrapThrowable(ex) => pf(unwrapThrowable(ex))
}
+ private def systemProperties: Iterator[(String, String)] = {
+ import scala.collection.JavaConverters._
+ System.getProperties.asScala.iterator
+ }
+
+ private def searchForBootClasspath = (
+ systemProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse ""
+ )
+
+ def show(cl: ClassLoader) = {
+ def inferClasspath(cl: ClassLoader) = cl match {
+ case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
+ case _ => "<unknown>"
+ }
+ cl match {
+ case cl if cl != null =>
+ "%s of type %s with classpath %s".format(cl, cl.getClass, inferClasspath(cl))
+ case null =>
+ "primordial classloader with boot classpath [%s]".format(searchForBootClasspath)
+ }
+ }
+
def defaultReflectionClassLoader() = {
// say no to non-determinism of mirror classloaders
// default classloader will be instantiated using current system classloader
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 1738642932..6f40a3ac3e 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -3,6 +3,7 @@ package scala
package object reflect {
import ReflectionUtils._
+ import scala.compat.Platform.EOL
// !!! This was a val; we can't throw exceptions that aggressively without breaking
// non-standard environments, e.g. google app engine. I made it a lazy val, but
@@ -12,15 +13,69 @@ package object reflect {
// todo. default mirror (a static object) might become a source for memory leaks (because it holds a strong reference to a classloader)!
lazy val mirror: api.Mirror = mkMirror(defaultReflectionClassLoader)
+ private def mirrorDiagnostics(cl: ClassLoader): String = """
+ |
+ | This error has happened because `scala.reflect.runtime.package` located in
+ | scala-compiler.jar cannot be loaded. Classloader you are using is:
+ | %s.
+ |
+ | In Scala 2.10.0 M3, scala-compiler.jar is required to be on the classpath
+ | for manifests and type tags to function. This will change in the final release,
+ | but for now you need to adjust your scripts or build system to proceed.
+ | Here are the instructions for some of the situations that might be relevant.
+ |
+ | If you compile your application directly from the command line
+ | or a hand-rolled script, this is a bug. Please, report it.
+ |
+ | If you compile your application with Maven using the maven-scala plugin,
+ | set its "fork" configuration entry to "false:
+ |
+ | <plugin>
+ | <groupId>org.scala-tools</groupId>
+ | <artifactId>maven-scala-plugin</artifactId>
+ | <version>2.15.0</version>
+ | <executions>
+ | <execution>
+ | <goals>
+ | ...
+ | </goals>
+ | <configuration>
+ | <fork>false</fork>
+ | ...
+ | </configuration>
+ | </execution>
+ | </executions>
+ | </plugin>
+ |
+ | If you compile your application with SBT,
+ | <to be implemented: release SBT for 2.10.0 M3>
+ |
+ | If you compile your application in Scala IDE,
+ | <to be implemented: release Scala IDE for 2.10.0 M3>.
+ |
+ | If you launch your application directly from the command line
+ | or a hand-rolled script, add `scala-compiler.jar` to the classpath:
+ |
+ | scalac HelloWorld.scala
+ | scala HelloWorld -cp path/to/scala-compiler.jar
+ |
+ | If you launch your application with Maven using the maven-scala plugin,
+ | set its "fork" configuration entry to "false as shown above.
+ |
+ | If you launch your application with SBT, make sure that you use
+ | <to be implemented: release SBT for 2.10.0 M3>
+ |
+ | If you launch your application in Scala IDE, make sure that both scala-library.jar and scala-compiler.jar
+ | are in bootstrap entries on the classpath of your launch configuration.
+ """.stripMargin('|').format(show(cl))
+
def mkMirror(classLoader: ClassLoader): api.Mirror = {
- // we use (Java) reflection here so that we can keep reflect.runtime and reflect.internals in a seperate jar
- // note that we must instantiate the mirror with current classloader, otherwise we won't be able to cast it to api.Mirror
- // that's not a problem, though, because mirror can service classes from arbitrary classloaders
- val instance = invokeFactoryOpt(getClass.getClassLoader, "scala.reflect.runtime.package", "mkMirror", classLoader)
+ val coreClassLoader = getClass.getClassLoader
+ val instance = invokeFactoryOpt(coreClassLoader, "scala.reflect.runtime.package", "mkMirror", classLoader)
instance match {
case Some(x: api.Mirror) => x
- case Some(_) => throw new UnsupportedOperationException("Available scala reflection implementation is incompatible with this interface")
- case None => throw new UnsupportedOperationException("Scala reflection not available on this platform")
+ case Some(_) => throw new UnsupportedOperationException("Available scala reflection implementation is incompatible with this interface." + mirrorDiagnostics(coreClassLoader))
+ case None => throw new UnsupportedOperationException("Scala reflection not available on this platform." + mirrorDiagnostics(coreClassLoader))
}
}