summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/examples/mobile/sort.scala17
-rw-r--r--sources/scala/mobile/Code.scala230
-rw-r--r--sources/scala/mobile/Location.scala75
3 files changed, 322 insertions, 0 deletions
diff --git a/sources/examples/mobile/sort.scala b/sources/examples/mobile/sort.scala
new file mode 100644
index 0000000000..62818467fa
--- /dev/null
+++ b/sources/examples/mobile/sort.scala
@@ -0,0 +1,17 @@
+package examples.mobile;
+
+import java.net._;
+import scala.mobile._;
+
+
+object sort with Application {
+ val url = new URL("http://scala.epfl.ch/classes/examples.jar");
+
+ val location = new Location(url);
+ val obj = location create "examples.sort";
+ val ar = Array(6, 2, 8, 5, 1);
+ obj[Array[Int], Unit]("println")(ar);
+ obj[Array[Int], Unit]("sort")(ar);
+ obj[Array[Int], Unit]("println")(ar);
+ Console.println
+}
diff --git a/sources/scala/mobile/Code.scala b/sources/scala/mobile/Code.scala
new file mode 100644
index 0000000000..79d9eaca10
--- /dev/null
+++ b/sources/scala/mobile/Code.scala
@@ -0,0 +1,230 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.mobile;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+
+/** The clase <code>Code</code> provides <code>apply</code> methods
+ * with different arities (actually up to 9 parameters) to invoke
+ * a function simply by specifying its name and argument types.
+ *
+ * Example:<pre>
+ * val url = new URL("http://scala.epfl.ch/classes/examples.jar");
+ * val obj = new Location(url) create "examples.sort";
+ * val ar = Array(6, 2, 8, 5, 1);
+ * obj[Array[Int], Unit]("println")(ar);
+ * obj[Array[Int], Unit]("sort")(ar);
+ * obj[Array[Int], Unit]("println")(ar);</pre>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+class Code(clazz: java.lang.Class) {
+
+ private type JObject = java.lang.Object;
+
+ private var instance: JObject = _;
+
+ ///////////////////////////// apply methods ///////////////////////////////
+
+ def apply[R](funName: String) =
+ () => {
+ val args = Predef.Array[JObject]();
+ val types = Predef.Array[Class]();
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, R](funName: String) =
+ (_0: A0) => {
+ val p = boxValue(_0);
+ val args = Predef.Array(p._1);
+ val types = Predef.Array(p._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, R](funName: String) =
+ (_0: A0, _1: A1) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val args = Predef.Array(p0._1, p1._1);
+ val types = Predef.Array(p0._2, p1._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, A2, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val p2 = boxValue(_2);
+ val args = Predef.Array(p0._1, p1._1, p2._1);
+ val types = Predef.Array(p0._2, p1._2, p2._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, A2, A3, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val p2 = boxValue(_2);
+ val p3 = boxValue(_3);
+ val args = Predef.Array(p0._1, p1._1, p2._1, p3._1);
+ val types = Predef.Array(p0._2, p1._2, p2._2, p3._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, A2, A3, A4, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val p2 = boxValue(_2);
+ val p3 = boxValue(_3);
+ val p4 = boxValue(_4);
+ val args = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1);
+ val types = Predef.Array(p0._2, p1._2, p2._2, p3._2, p4._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, A2, A3, A4, A5, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val p2 = boxValue(_2);
+ val p3 = boxValue(_3);
+ val p4 = boxValue(_4);
+ val p5 = boxValue(_5);
+ val args = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1);
+ val types = Predef.Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, A2, A3, A4, A5, A6, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5, _6: A6) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val p2 = boxValue(_2);
+ val p3 = boxValue(_3);
+ val p4 = boxValue(_4);
+ val p5 = boxValue(_5);
+ val p6 = boxValue(_6);
+ val args = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1);
+ val types = Predef.Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2, p6._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, A2, A3, A4, A5, A6, A7, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5, _6: A6, _7: A7) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val p2 = boxValue(_2);
+ val p3 = boxValue(_3);
+ val p4 = boxValue(_4);
+ val p5 = boxValue(_5);
+ val p6 = boxValue(_6);
+ val p7 = boxValue(_7);
+ val args = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1, p7._1);
+ val types = Predef.Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2, p6._2, p7._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, A1, A2, A3, A4, A5, A6, A7, A8, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5, _6: A6, _7: A7, _8: A8) => {
+ val p0 = boxValue(_0);
+ val p1 = boxValue(_1);
+ val p2 = boxValue(_2);
+ val p3 = boxValue(_3);
+ val p4 = boxValue(_4);
+ val p5 = boxValue(_5);
+ val p6 = boxValue(_6);
+ val p7 = boxValue(_7);
+ val p8 = boxValue(_8);
+ val args = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1, p7._1, p8._1);
+ val types = Predef.Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2, p6._2, p7._2, p8._2);
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ ////////////////////// private functions ///////////////////////
+
+ private def boxValue(value: Any) = value match {
+ case x: Byte => Pair(new java.lang.Byte(x), java.lang.Byte.TYPE)
+ case x: Boolean => Pair(new java.lang.Boolean(x), java.lang.Boolean.TYPE)
+ case x: Char => Pair(new java.lang.Character(x), java.lang.Character.TYPE)
+ case x: Short => Pair(new java.lang.Short(x), java.lang.Short.TYPE)
+ case x: Int => Pair(new java.lang.Integer(x), java.lang.Integer.TYPE)
+ case x: Long => Pair(new java.lang.Long(x), java.lang.Long.TYPE)
+ case x: Float => Pair(new java.lang.Float(x), java.lang.Float.TYPE)
+ case x: Double => Pair(new java.lang.Double(x), java.lang.Double.TYPE)
+ case _ =>
+ val x = value.asInstanceOf[JObject];
+ Pair(x, x.getClass())
+ }
+
+ private def isConstructorName(methName: String) = {
+ var className = clazz.getName();
+ val classInx = className.lastIndexOf(".");
+ val methInx = methName.lastIndexOf(".");
+ if (classInx > 0 && methInx < 0)
+ className = className.substring(classInx + 1, className.length());
+ methName.equals(className)
+ }
+
+ private def applyFun(methName: String, args: Array[JObject], argTypes: Array[Class]): JObject = {
+ try {
+ val method = clazz.getMethod(methName, argTypes);
+ var obj: JObject = null;
+ if (! Modifier.isStatic(method.getModifiers())) {
+ if (instance == null) {
+ instance = try {
+ clazz.newInstance();
+ } catch { case _ =>
+ val cs = clazz.getConstructors();
+//Console.println("cs.length=" + cs.length);
+ if (cs.length > 0) {
+ cs(0).newInstance(Predef.Array(""))
+ } else {
+ error("class " + clazz.getName() + " has no public constructor");
+ null
+ }
+ }
+ }
+ obj = instance;
+ }
+ val result = method.invoke(obj, args);
+ if (result == null) ().asInstanceOf[JObject] else result
+ }
+ catch {
+ case me: NoSuchMethodException =>
+ if (isConstructorName(methName)) {
+ try {
+ val cstr = clazz.getConstructor(argTypes);
+ instance = cstr.newInstance(args);
+ instance
+ }
+ catch {
+ case e: Exception =>
+ Console.println(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ else {
+ Console.println(me.getMessage());
+ me.printStackTrace();
+ }
+ null
+ case e: Exception =>
+ Console.println(e.getMessage());
+ e.printStackTrace();
+ null
+ }
+ }
+
+}
diff --git a/sources/scala/mobile/Location.scala b/sources/scala/mobile/Location.scala
new file mode 100644
index 0000000000..7c8d787caf
--- /dev/null
+++ b/sources/scala/mobile/Location.scala
@@ -0,0 +1,75 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.mobile;
+
+import java.net._;
+
+import scala.collection.mutable._;
+
+
+/** The class <code>Location</code> provides a <code>create</code>
+ * method to instanciate objects from a network location by
+ * specifying its URL address.
+ *
+ * Example:<pre>
+ * val url = new URL("http://scala.epfl.ch/classes/examples.jar");
+ * val obj = new Location(url) create "examples.sort";</pre>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+class Location(url: URL) {
+
+ /** A cache containing all class loaders of this location.
+ */
+ private var lcache: Map[URL, ClassLoader] = new HashMap;
+
+ /** The class loader associated with this location.
+ */
+ private val loader = if (url == null)
+ ClassLoader.getSystemClassLoader()
+ else
+ lcache.get(url) match {
+ case Some(cl) =>
+ cl
+ case _ =>
+ val cl = new URLClassLoader(Predef.Array(url));
+ lcache(url) = cl;
+ cl
+ };
+
+ /** A cache containing all classes of this location.
+ */
+ private var ccache: Map[String, java.lang.Class] = new HashMap;
+
+ def create(className: String): Code = {
+ val clazz = ccache.get(className) match {
+ case Some(x) =>
+ x
+ case _ =>
+ val clazz = if (loader.loadClass(className).isInterface()) {
+ // Scala source: class A { ... };
+ // Java bytecode: interface A.class + class A$class.class
+ loader.loadClass(className + "$class");
+ }
+ else {
+ // Scala source: object A { ... };
+ // Java bytecode: interface A.class + class A$.class
+ loader.loadClass(className + "$");
+ }
+ ccache(className) = clazz;
+ clazz
+ };
+ new Code(clazz)
+ }
+
+}
+
+object Location extends Location(null);