summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
*/
-
}