diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-04-15 11:36:43 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-04-15 12:04:23 +0200 |
commit | 967ceb28ab2737ee16112b4c9be46419f43b9a99 (patch) | |
tree | 8ed0aa510de435e3f64316ea4cc1cb466d8c9f38 | |
parent | 364dd41c3e0e33afe6c3ec6e0c04f1d345c4b6ca (diff) | |
download | scala-967ceb28ab2737ee16112b4c9be46419f43b9a99.tar.gz scala-967ceb28ab2737ee16112b4c9be46419f43b9a99.tar.bz2 scala-967ceb28ab2737ee16112b4c9be46419f43b9a99.zip |
big fat error message for default mirror failures
-rw-r--r-- | src/library/scala/reflect/ReflectionUtils.scala | 22 | ||||
-rw-r--r-- | src/library/scala/reflect/package.scala | 67 |
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)) } } |