summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-08-23 21:15:20 +0000
committerPaul Phillips <paulp@improving.org>2011-08-23 21:15:20 +0000
commit3a1463cd833175bdaa7a31d96a41a0d926b0e9db (patch)
treed770316544eff5144e34ec54353b06d6cbe20fe5
parente69822117c99a6c79a69a5b4dde3a82040400bb3 (diff)
downloadscala-3a1463cd833175bdaa7a31d96a41a0d926b0e9db.tar.gz
scala-3a1463cd833175bdaa7a31d96a41a0d926b0e9db.tar.bz2
scala-3a1463cd833175bdaa7a31d96a41a0d926b0e9db.zip
Modified scala.reflect package object not to th...
Modified scala.reflect package object not to throw an exception at initialization time if it can't instantiate the value in question. Review by odersky.
-rw-r--r--src/library/scala/reflect/ReflectionUtils.scala37
-rw-r--r--src/library/scala/reflect/package.scala16
2 files changed, 46 insertions, 7 deletions
diff --git a/src/library/scala/reflect/ReflectionUtils.scala b/src/library/scala/reflect/ReflectionUtils.scala
new file mode 100644
index 0000000000..c2f89102cb
--- /dev/null
+++ b/src/library/scala/reflect/ReflectionUtils.scala
@@ -0,0 +1,37 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect
+
+import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException }
+
+/** A few java-reflection oriented utility functions useful during reflection bootstrapping.
+ */
+trait ReflectionUtils {
+ // Unwraps some chained exceptions which arise during reflective calls.
+ def unwrapThrowable(x: Throwable): Throwable = x match {
+ case _: InvocationTargetException | // thrown by reflectively invoked method or constructor
+ _: ExceptionInInitializerError | // thrown when running a static initializer (e.g. a scala module constructor)
+ _: UndeclaredThrowableException | // invocation on a proxy instance if its invocation handler's `invoke` throws an exception
+ _: ClassNotFoundException | // no definition for a class instantiated by name
+ _: NoClassDefFoundError // the definition existed when the executing class was compiled, but can no longer be found
+ if x.getCause != null =>
+ unwrapThrowable(x.getCause)
+ case _ => x
+ }
+ // Transforms an exception handler into one which will only receive the unwrapped
+ // exceptions (for the values of wrap covered in unwrapThrowable.)
+ def unwrapForHandler[T](pf: PartialFunction[Throwable, T]): PartialFunction[Throwable, T] = {
+ case ex if pf isDefinedAt unwrapThrowable(ex) => pf(unwrapThrowable(ex))
+ }
+
+ // Retrieves the MODULE$ field for the given class name.
+ def singletonInstance(className: String, cl: ClassLoader = getClass.getClassLoader): Option[AnyRef] = {
+ val name = if (className endsWith "$") className else className + "$"
+
+ try Some(java.lang.Class.forName(name, true, cl) getField "MODULE$" get null)
+ catch { case _: ClassNotFoundException => None }
+ }
+}
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index eac4adcffe..ad541ce46e 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -1,18 +1,20 @@
package scala
-package object reflect {
-
- val mirror: api.Mirror = try {
+package object reflect extends ReflectionUtils {
+ // !!! 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
+ // I think it would be better yet to throw the exception somewhere else - not during
+ // initialization, but in response to a doomed attempt to utilize it.
+ lazy val mirror: api.Mirror = {
// we use (Java) reflection here so that we can keep reflect.runtime and reflect.internals in a seperate jar
- (java.lang.Class forName "scala.reflect.runtime.Mirror$" getField "MODULE$" get null).asInstanceOf[api.Mirror]
- } catch {
- case ex: NoClassDefFoundError =>
+ singletonInstance("scala.reflect.runtime.Mirror") collect { case x: api.Mirror => x } getOrElse {
throw new UnsupportedOperationException("Scala reflection not available on this platform")
+ }
}
+
/** Uncomment once we got rid of the old Symbols, Types, Trees
type Symbol = mirror.Symbol
type Type = mirror.Type
type Tree = mirror.Tree
*/
-
}