summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-06-12 20:48:56 +0000
committerPaul Phillips <paulp@improving.org>2009-06-12 20:48:56 +0000
commit8d8d1c314706143ef9e21978642df3315fb4a04b (patch)
tree75d40673b51168dec35537ae2ee783d470d78698 /src
parentb72cc0bda59df3b73afb128b24d86b0cbb1fbf43 (diff)
downloadscala-8d8d1c314706143ef9e21978642df3315fb4a04b.tar.gz
scala-8d8d1c314706143ef9e21978642df3315fb4a04b.tar.bz2
scala-8d8d1c314706143ef9e21978642df3315fb4a04b.zip
A RichClass for the java side which offers type...
A RichClass for the java side which offers typed Constructors. Working around bug #1560 and improving on the java interface. Also a small experiment in the reflection department.
Diffstat (limited to 'src')
-rw-r--r--src/dotnet-library/scala/runtime/RichClass.scala4
-rw-r--r--src/library/scala/reflect/RichClass.scala91
-rw-r--r--src/library/scala/util/ClassLoader.scala19
3 files changed, 94 insertions, 20 deletions
diff --git a/src/dotnet-library/scala/runtime/RichClass.scala b/src/dotnet-library/scala/runtime/RichClass.scala
index d8ce949410..a7a781f613 100644
--- a/src/dotnet-library/scala/runtime/RichClass.scala
+++ b/src/dotnet-library/scala/runtime/RichClass.scala
@@ -13,8 +13,8 @@ package scala.runtime
import Predef.Class
-final class RichClass(val self: Class[_]) extends Proxy {
-
+final class RichClass(val self: Class[_]) extends Proxy
+{
def isPrimitive(): Boolean = self.IsPrimitive
def isArray(): Boolean = self.IsArray
diff --git a/src/library/scala/reflect/RichClass.scala b/src/library/scala/reflect/RichClass.scala
new file mode 100644
index 0000000000..f016fb37dc
--- /dev/null
+++ b/src/library/scala/reflect/RichClass.scala
@@ -0,0 +1,91 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect
+
+import util.control.Exception._
+import util.ScalaClassLoader._
+import java.lang.{ Class => JClass }
+import java.lang.reflect. { Constructor => JConstructor }
+
+object RichClass
+{
+ // We can't put this in Predef at the moment because everything referenced
+ // from Predef has to be buildable at the first bootstraping phase.
+ implicit def classWrapper[T](x: JClass[T]): RichClass[T] = new RichClass(x)
+}
+
+final class RichClass[T](val self: JClass[T]) extends Proxy
+{
+ // The getConstructors and getDeclaredConstructors methods on java.lang.Class[T]
+ // return "raw type" Constructors rather than Constructor[T]s as one would want.
+ // The "why" from http://java.sun.com/javase/6/docs/api/java/lang/Class.html is:
+ //
+ // Note that while this method returns an array of Constructor<T> objects (that is an array
+ // of constructors from this class), the return type of this method is Constructor<?>[] and
+ // not Constructor<T>[] as might be expected. This less informative return type is necessary
+ // since after being returned from this method, the array could be modified to hold Constructor
+ // objects for different classes, which would violate the type guarantees of Constructor<T>[]
+ //
+ // Since this reasoning is invalid in scala due to its abandonment of Array covariance,
+ // these methods exist to correct the return types.
+ //
+ // In addition, at this writing because of ticket #1560 the compiler crashes on the
+ // untyped constructors but not on these.
+
+ def getConstructorsTyped(): Array[JConstructor[T]] =
+ self.getConstructors() map (_.asInstanceOf[JConstructor[T]])
+
+ def getDeclaredConstructorsTyped(): Array[JConstructor[T]] =
+ self.getDeclaredConstructors() map (_.asInstanceOf[JConstructor[T]])
+
+ private lazy val classLoader = self.getClassLoader match {
+ case null => getSystemLoader
+ case x => x
+ }
+ private val exceptions = List(
+ classOf[ClassNotFoundException],
+ classOf[NoSuchMethodException],
+ classOf[SecurityException],
+ classOf[NullPointerException],
+ classOf[ClassCastException]
+ )
+
+ // Experimental!
+ // scala> classOf[String].reflectiveCall[Array[String]]("ababab", "split")("b")
+ // res0: Array[String] = Array(a, a, a)
+
+ /** A class representing a reflective method call. It is a function object
+ * and will make the call with whatever args are given via apply, or it will
+ * throw an exception at that point if there was an error in creation.
+ */
+ class ReflectiveCall[+U](obj: T, name: String) {
+ def methodForArgs(args: AnyRef*) = self.getMethod(name, args map (_.getClass) : _*)
+ def isErroneous = false
+ def apply(args: Any*): U = {
+ val ps = args map (_.asInstanceOf[AnyRef])
+ val m = methodForArgs(ps: _*)
+ m.invoke(obj, ps: _*).asInstanceOf[U]
+ }
+ }
+
+ class FailedReflectiveCall[+U](ex: Throwable) extends ReflectiveCall[U](null.asInstanceOf[T], null) {
+ override def isErroneous = true
+ override def apply(args: Any*) = throw ex
+ }
+
+ def reflectiveCall[U](obj: T, method: String): ReflectiveCall[U] = {
+ (catching(exceptions: _*) either (new ReflectiveCall[U](obj, method))) match {
+ case Left(x) => new FailedReflectiveCall[U](x)
+ case Right(x) => x
+ }
+ }
+}
+
diff --git a/src/library/scala/util/ClassLoader.scala b/src/library/scala/util/ClassLoader.scala
index 503fdc7202..5663b5b74f 100644
--- a/src/library/scala/util/ClassLoader.scala
+++ b/src/library/scala/util/ClassLoader.scala
@@ -6,7 +6,7 @@
package scala.util
import java.lang.{ ClassLoader => JavaClassLoader }
-import java.lang.reflect.{ Modifier, Method }
+import java.lang.reflect.{ Constructor, Modifier, Method }
import java.net.URL
import ScalaClassLoader._
import scala.util.control.Exception.{ catching }
@@ -69,23 +69,6 @@ object ScalaClassLoader {
def getSystemLoader() = JavaClassLoader.getSystemClassLoader()
def defaultParentClassLoader() = findExtClassLoader()
- /** XXX move this to RichClass. */
- def callReflectively[T](clazz: Class[_], obj: String, method: String, args: Any*): Option[T] = {
- val exceptions = List(
- classOf[ClassNotFoundException],
- classOf[NoSuchMethodException],
- classOf[SecurityException],
- classOf[NullPointerException],
- classOf[ClassCastException]
- )
-
- catching(exceptions: _*) opt {
- val o: Class[_] = clazz.getClassLoader loadClass obj
- val m: Method = o getDeclaredMethod method
- m.invoke(o, args map (_.asInstanceOf[AnyRef]) : _*).asInstanceOf[T]
- }
- }
-
def fromURLs(urls: Seq[URL]): URLClassLoader =
new URLClassLoader(urls.toList, defaultParentClassLoader())