summaryrefslogtreecommitdiff
path: root/src/detach/library
diff options
context:
space:
mode:
authormichelou <michelou@epfl.ch>2010-11-17 12:26:13 +0000
committermichelou <michelou@epfl.ch>2010-11-17 12:26:13 +0000
commitc09f6173e96ec741c9b38edfee969ae8c6b74d4e (patch)
tree1f06579f72afa12092acd0b5bbb7c678291cf619 /src/detach/library
parent363a1456f671323b35dcacf2c8b8eb39180b8a53 (diff)
downloadscala-c09f6173e96ec741c9b38edfee969ae8c6b74d4e.tar.gz
scala-c09f6173e96ec741c9b38edfee969ae8c6b74d4e.tar.bz2
scala-c09f6173e96ec741c9b38edfee969ae8c6b74d4e.zip
updates Scala examples, added detach plugin
Diffstat (limited to 'src/detach/library')
-rw-r--r--src/detach/library/scala/remoting/Channel.scala192
-rw-r--r--src/detach/library/scala/remoting/Debug.scala27
-rw-r--r--src/detach/library/scala/remoting/ServerChannel.scala68
-rw-r--r--src/detach/library/scala/remoting/detach.scala49
-rw-r--r--src/detach/library/scala/runtime/RemoteRef.scala182
-rw-r--r--src/detach/library/scala/runtime/remoting/Debug.scala85
-rw-r--r--src/detach/library/scala/runtime/remoting/RegistryDelegate.scala192
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteBooleanRef.scala51
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteByteRef.scala51
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteCharRef.scala51
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteDoubleRef.scala50
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteFloatRef.scala50
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteGC.scala67
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteIntRef.scala51
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteLongRef.scala51
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteObjectRef.scala51
-rw-r--r--src/detach/library/scala/runtime/remoting/RemoteShortRef.scala50
17 files changed, 1318 insertions, 0 deletions
diff --git a/src/detach/library/scala/remoting/Channel.scala b/src/detach/library/scala/remoting/Channel.scala
new file mode 100644
index 0000000000..6b1fbcee4e
--- /dev/null
+++ b/src/detach/library/scala/remoting/Channel.scala
@@ -0,0 +1,192 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Channel.scala 18365 2009-07-21 11:00:42Z michelou $
+
+package scala.remoting
+
+import java.io._
+import java.net._
+import java.rmi.server.RMIClassLoader
+
+/** <p>
+ * The class <code>Channel</code> implements (basic) typed channels
+ * which use <a href="http://java.sun.com/docs/books/tutorial/networking/sockets/"
+ * target="_top"/>Java socket</a> communication and Scala type manifests to
+ * provide type-safe send/receive operations between a localhost and another
+ * remote machine by specifying some <code>host</code> and <code>port</code>.
+ * </p>
+ *
+ * @author Stephane Micheloud
+ * @version 1.1
+ */
+class Channel protected (socket: Socket) {
+
+ // Create a socket without a timeout
+ def this(host: String, port: Int) = this(new Socket(host, port))
+
+ // // Create a socket with a timeout
+ // val sockaddr: SocketAddress = new InetSocketAddress(addr, port)
+ // val socket = new Socket()
+ // // If the timeout occurs, SocketTimeoutException is thrown.
+ // socket.connect(sockaddr, 2000) // 2 seconds
+
+ /** Returns the local address of this channel. */
+ val host = socket.getInetAddress.getHostAddress
+
+ /** Returns the port on which this channel is listening. */
+ val port = socket.getLocalPort
+
+ private var cl: ClassLoader =
+ try {
+ // requires permission in Java policy file
+ val codebase = System.getProperty("java.rmi.server.codebase")
+ if (codebase != null) info("codebase="+codebase)
+ RMIClassLoader.getClassLoader(codebase)
+ }
+ catch {
+ case e: Exception =>
+ error("Class loader undefined: " + e.getMessage)
+ null
+ }
+ def classLoader: ClassLoader = cl
+ def classLoader_=(x: ClassLoader) { cl = x }
+
+ info(""+this)
+
+ private class CustomObjectInputStream(in: InputStream)
+ extends ObjectInputStream(in) {
+ override def resolveClass(desc: ObjectStreamClass): Class[_] =
+ if (cl eq null)
+ super.resolveClass(desc)
+ else
+ try {
+ info("resolve class "+desc.getName)
+ cl loadClass desc.getName
+ }
+ catch {
+ case e: ClassNotFoundException =>
+ super.resolveClass(desc)
+ }
+ }
+/*
+ // lazy modifier is required!
+ private lazy val in =
+ try {
+ new CustomObjectInputStream(socket.getInputStream)
+ }
+ catch {
+ case e: IOException =>
+ error("Input stream undefined: "+e.getMessage+" ("+this+")")
+ null
+ }
+ private lazy val out =
+ try {
+ new ObjectOutputStream(socket.getOutputStream)
+ }
+ catch {
+ case e: IOException =>
+ error("Output stream undefined: "+e.getMessage+" ("+this+")")
+ null
+ }
+*/
+ /** <code>receive&lt;primtype&gt;</code> methods may throw an
+ * <code>IOException</code>.
+ */
+ def receiveUnit = receive[Unit]
+ def receiveBoolean = receive[Boolean]
+ def receiveByte = receive[Byte]
+ def receiveChar = receive[Char]
+ def receiveShort = receive[Short]
+ def receiveInt = receive[Int]
+ def receiveLong = receive[Long]
+ def receiveFloat = receive[Float]
+ def receiveDouble = receive[Double]
+ def receiveString = receive[String]
+
+ /** <code>receive</code> method may throw either an
+ * <code>ClassNotFoundException</code> or an <code>IOException</code>.
+ *
+ * @throw <code>ChannelException</code> if received value has not
+ * the expected type.
+ */
+ @throws(classOf[ChannelException])
+ def receive[T](implicit expected: reflect.Manifest[T]): T = {
+ val in = new CustomObjectInputStream(socket.getInputStream)
+ val found = in.readObject().asInstanceOf[reflect.Manifest[_]]
+ info("receive: found="+found+", expected="+expected)
+ import scala.reflect.Manifest
+ val x = found match {
+ case Manifest.Unit => ()
+ case Manifest.Boolean => in.readBoolean()
+ case Manifest.Byte => in.readByte()
+ case Manifest.Char => in.readChar()
+ case Manifest.Short => in.readShort()
+ case Manifest.Int => in.readInt()
+ case Manifest.Long => in.readLong()
+ case Manifest.Float => in.readFloat()
+ case Manifest.Double => in.readDouble()
+ case _ => in.readObject()
+ }
+ val res = if (found <:< expected)
+ x.asInstanceOf[T]
+ else
+ throw new ChannelException(
+ "\n\tfound \""+found+"\"\n\texpected \""+expected+"\"")
+ info("received "+res+" (available="+in.available+")")
+ res
+ }
+
+ /** <code>?</code> method may throw either an
+ * <code>ClassNotFoundException</code> or an <code>IOException</code>.
+ */
+ def ?[T](implicit m: reflect.Manifest[T]): T = receive[T](m)
+
+ /** <code>send</code> method may throw an <code>IOException</code>.
+ */
+ def send[T](x: T)(implicit m: reflect.Manifest[T]) {
+ val out = new ObjectOutputStream(socket.getOutputStream)
+ out writeObject m
+ x match {
+ case x: Unit => // nop
+ case x: Boolean => out writeBoolean x
+ case x: Byte => out writeByte x
+ case x: Char => out writeChar x
+ case x: Short => out writeShort x
+ case x: Int => out writeInt x
+ case x: Long => out writeLong x
+ case x: Float => out writeFloat x
+ case x: Double => out writeDouble x
+ case x => out writeObject x
+ }
+ out.flush()
+ info("sent "+x)
+ }
+
+ /** <code>!</code> method may throw an <code>IOException</code>.
+ */
+ def ![T](x: T)(implicit m: reflect.Manifest[T]) { send(x)(m) }
+
+ def close() {
+ try { socket.close() }
+ catch { case e: IOException => }
+ info(this+" closed")
+ }
+
+ override def toString: String = socket.toString
+
+ private def info(msg: String) {
+ runtime.remoting.Debug.info("[Channel] "+msg)
+ }
+}
+
+/** <code>ChannelException</code> may be thrown by the operation
+ * <code>receive</code> when the received data has not the expected type.
+ */
+case class ChannelException(msg: String) extends IOException(msg)
+
diff --git a/src/detach/library/scala/remoting/Debug.scala b/src/detach/library/scala/remoting/Debug.scala
new file mode 100644
index 0000000000..6a63b8a25d
--- /dev/null
+++ b/src/detach/library/scala/remoting/Debug.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2007-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Debug.scala 17412 2009-03-31 10:08:25Z michelou $
+
+package scala.remoting
+
+/**
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+object Debug extends runtime.remoting.Debug {
+ private val f = new java.text.SimpleDateFormat("HH:mm:ss")
+ private val c = new java.util.GregorianCalendar
+
+ def getTime: String = f format c.getTime
+
+ def getLocation(obj: AnyRef): String = {
+ val s = obj.getClass().getClassLoader().toString()
+ s.substring(s.indexOf('['))
+ }
+}
diff --git a/src/detach/library/scala/remoting/ServerChannel.scala b/src/detach/library/scala/remoting/ServerChannel.scala
new file mode 100644
index 0000000000..6f9fe0a594
--- /dev/null
+++ b/src/detach/library/scala/remoting/ServerChannel.scala
@@ -0,0 +1,68 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ServerChannel.scala 18365 2009-07-21 11:00:42Z michelou $
+
+package scala.remoting
+
+import java.net.{ServerSocket, Socket}
+
+/** <p>
+ * Creates a server channel and binds its associated socket to the
+ * specified port number.<br/>
+ * Example:
+ * </p><pre>
+ * <b>class</b> ComputeChannel(s: Socket) <b>extends</b> Channel(s) {
+ * <b>def</b> receiveFunc = receive[Int => Int]
+ * }
+ * <b>class</b> ComputeServer(p: Int)
+ * <b>extends</b> AbstractServerChannel[ComputeChannel](p) {
+ * <b>def</b> newChannel(s: Socket) = <b>new</b> ComputeChannel(s)
+ * }</pre>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class ServerChannel(p: Int) extends AbstractServerChannel[Channel](p) {
+ def newChannel(s: Socket) = new Channel(s)
+}
+
+abstract class AbstractServerChannel[T <: Channel](_port: Int) {
+
+ /** Creates an input channel and binds its associated socket to any
+ * free port.
+ */
+ def this() = this(0)
+
+ // The maximum queue length for incoming requests to connect is set to 50.
+ private val serverSocket = new ServerSocket(_port)
+
+ /** Returns the local address of this channel. */
+ val host = serverSocket.getInetAddress.getHostAddress
+
+ /** Returns the port on which this channel is listening. */
+ val port = serverSocket.getLocalPort
+ info("Listening on port "+port)
+
+ protected def newChannel(socket: Socket): T
+
+ def accept: T = {
+ System.gc() // required!
+ newChannel(serverSocket.accept)
+ }
+
+ def close() {
+ try { serverSocket.close() }
+ catch { case e: java.io.IOException => }
+ info("Server socket "+host+":"+port+" closed")
+ }
+
+ protected def info(msg: String) {
+ runtime.remoting.Debug.info("[ServerChannel] "+msg)
+ }
+}
diff --git a/src/detach/library/scala/remoting/detach.scala b/src/detach/library/scala/remoting/detach.scala
new file mode 100644
index 0000000000..d0fb694af5
--- /dev/null
+++ b/src/detach/library/scala/remoting/detach.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: detach.scala 16901 2009-01-13 15:37:05Z michelou $
+
+package scala.remoting
+
+
+/** The <code>detach</code> object is a <em>marker object</em> which informs
+ * the Scala compiler that arguments whose type is a function type are
+ * eligible for remote closure generation.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 13/07/2005
+ */
+object detach {
+
+ def apply[R](f: Function0[R]): Function0[R] = f
+ def apply[T0, R](f: Function1[T0, R]): Function1[T0, R] = f
+ def apply[T0, T1, R](f: Function2[T0, T1, R]): Function2[T0, T1, R] = f
+ def apply[T0, T1, T2, R](f: Function3[T0, T1, T2, R]): Function3[T0, T1, T2, R] = f
+ def apply[T0, T1, T2, T3, R](f: Function4[T0, T1, T2, T3, R]): Function4[T0, T1, T2, T3, R] = f
+ def apply[T0, T1, T2, T3, T4, R](f: Function5[T0, T1, T2, T3, T4, R]): Function5[T0, T1, T2, T3, T4, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, R](f: Function6[T0, T1, T2, T3, T4, T5, R]): Function6[T0, T1, T2, T3, T4, T5, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, R](f: Function7[T0, T1, T2, T3, T4, T5, T6, R]): Function7[T0, T1, T2, T3, T4, T5, T6, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, R](f: Function8[T0, T1, T2, T3, T4, T5, T6, T7, R]): Function8[T0, T1, T2, T3, T4, T5, T6, T7, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, R](f: Function9[T0, T1, T2, T3, T4, T5, T6, T7, T8, R]): Function9[T0, T1, T2, T3, T4, T5, T6, T7, T8, R] = f
+
+ // since 2.7.0
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R](f: Function10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R]): Function10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R](f: Function11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R]): Function11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R](f: Function12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R]): Function12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R](f: Function13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R]): Function13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R](f: Function14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R]): Function14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R](f: Function15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R]): Function15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R](f: Function16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R]): Function16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, R](f: Function17[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, R]): Function17[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, R](f: Function18[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, R]): Function18[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, R](f: Function19[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, R]): Function19[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, R](f: Function20[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, R]): Function20[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, R](f: Function21[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, R]): Function21[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, R] = f
+ def apply[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, R](f: Function22[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, R]): Function22[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, R] = f
+}
+
diff --git a/src/detach/library/scala/runtime/RemoteRef.scala b/src/detach/library/scala/runtime/RemoteRef.scala
new file mode 100644
index 0000000000..cd3d2045e2
--- /dev/null
+++ b/src/detach/library/scala/runtime/RemoteRef.scala
@@ -0,0 +1,182 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteRef.scala 18365 2009-07-21 11:00:42Z michelou $
+
+package scala.runtime
+
+import java.net.{InetAddress, MalformedURLException}
+import java.rmi.{NoSuchObjectException, NotBoundException, Remote}
+import java.rmi.registry.{LocateRegistry, Registry}
+import java.rmi.server.{ExportException, RemoteObject, UnicastRemoteObject}
+
+import scala.runtime.remoting.{Debug, RemoteGC}
+
+/**
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+object RemoteRef { /*extends Thread {
+ start()
+
+ private class QuitException extends Exception
+ private var isTerminated = false
+
+ // keeps track of live remote objects
+ val remoteGC = new RemoteGC
+
+ override def run() {
+ info("started thread")
+ try {
+ while (!isTerminated) {
+ this.synchronized {
+ try {
+ wait(200)
+ } catch {
+ case _: InterruptedException =>
+ if (isTerminated) throw new QuitException
+ }
+ remoteGC.gc()
+ if (remoteGC.allClosed)
+ throw new QuitException
+ } // synchronized
+
+ }
+ } catch {
+ case _: QuitException =>
+ // allow thread to exit
+ }
+ }
+*/
+ try {
+ val prop = System.getProperty("sun.rmi.dgc.server.gcInterval")
+ if (prop eq null)
+ System.setProperty("sun.rmi.dgc.server.gcInterval", "10000")
+ }
+ catch {
+ case e =>
+ error(e.getMessage)
+ }
+
+ private val host =
+ try {
+ val prop = System.getProperty("java.rmi.server.hostname")
+ if (prop ne null) prop else InetAddress.getLocalHost.getHostAddress
+ }
+ catch {
+ case e =>
+ warning(e.getMessage)
+ InetAddress.getLocalHost.getHostAddress
+ }
+
+ private val port =
+ try {
+ val prop = System.getProperty("scala.remoting.port")
+ if (prop ne null) prop.toInt else Registry.REGISTRY_PORT
+ }
+ catch {
+ case e =>
+ warning(e.getMessage)
+ Registry.REGISTRY_PORT // default port
+ }
+
+ private val registry =
+ try {
+ LocateRegistry.createRegistry(port)
+ }
+ catch {
+ case e =>
+ warning(e.getMessage)
+ LocateRegistry.getRegistry(host, port)
+ }
+
+ private val prefix = "//"+host+":"+port+"/"
+ printDebugInfos
+
+ // Variant 1: rebind/unbind
+ def bind(name: String, x: Remote): Remote =
+ try {
+ registry.rebind(prefix+name, x)
+ info("\""+prefix+name+"\" bound")
+ val stub = RemoteObject.toStub(x)
+ //remoteGC.newRef(stub)
+ stub
+ } catch {
+ case e: MalformedURLException =>
+ error(e.getMessage); null
+ case e: ExportException =>
+ info(""+e); null
+ case e: Exception => // AlreadyBoundException, etc..
+ throw e
+ }
+
+ def unbind(name: String) =
+ try {
+ registry.unbind(prefix+name)
+ info("\""+name+"\" unbound")
+ } catch {
+ case e: java.io.EOFException =>
+ warning(e.getMessage)
+ case e: NotBoundException =>
+ warning(e.getMessage+" already unbound")
+ case e: MalformedURLException =>
+ error(e.getMessage)
+ case e: Exception =>
+ throw e
+ }
+/*
+ // Variant 2: un-/exportObject
+ def bind(name: String, x: Remote): Remote =
+ try {
+ val ex = UnicastRemoteObject.exportObject(x)
+ registry.rebind(prefix+name, ex)
+ info("\""+prefix+name+"\" bound")
+ //val stub = RemoteObject.toStub(ex)
+ //remoteGC.newRef(ex)
+ ex //stub
+ } catch {
+ case e: MalformedURLException =>
+ error(e.getMessage); null
+ case e: ExportException =>
+ info(""+e); null
+ case e: Exception => // AlreadyBoundException, etc..
+ throw e
+ }
+
+ def unbind(x: Remote) {
+ try {
+ UnicastRemoteObject.unexportObject(x, false)
+ info("\""+x+"\" unbound")
+ } catch {
+ case e: java.io.EOFException =>
+ warning(e.getMessage)
+ case e: NotBoundException =>
+ warning(e.getMessage+" already unbound")
+ case e: MalformedURLException =>
+ error(e.getMessage)
+ case e: Exception =>
+ throw e
+ }
+ }
+*/
+ private def info(msg: String) { Debug.info("[RemoteRef] "+msg) }
+ private def warning(msg: String) { Debug.warning("[RemoteRef] "+msg) }
+ private def error(msg: String) { Debug.error("[RemoteRef] "+msg) }
+
+ private def printDebugInfos {
+ def property(name: String): String =
+ name+"="+(
+ try { System.getProperty(name, "") }
+ catch { case e => warning(e.getMessage); "?" })
+ info(property("java.rmi.server.hostname"))
+ info(property("sun.rmi.dgc.server.gcInterval"))
+ info("registry="+registry)
+ info("prefix="+prefix)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/Debug.scala b/src/detach/library/scala/runtime/remoting/Debug.scala
new file mode 100644
index 0000000000..f5e50eede4
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/Debug.scala
@@ -0,0 +1,85 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2007-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Debug.scala 17777 2009-05-19 18:16:25Z michelou $
+
+package scala.runtime.remoting
+
+/**
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+object Debug extends Debug {
+ override def info (msg: String) { if (lib) super.info(msg) }
+ override def verbose(msg: String) { if (lib) super.verbose(msg) }
+ override def warning(msg: String) { if (lib) super.warning(msg) }
+ override def error (msg: String) { if (lib) super.error(msg) }
+}
+
+/**
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class Debug(tag: String) {
+
+ def this() = this("")
+
+ object Level extends Enumeration {
+ type Level = Value
+ val SILENT, ERROR, WARNING, VERBOSE, INFO = Value
+ }
+
+ private val level0 =
+ try {
+ val prop = System.getProperty("scala.remoting.logLevel")
+ if (prop ne null) prop.toLowerCase else ""
+ }
+ catch {
+ case e =>
+ Console.err.println(e.getMessage)
+ ""
+ }
+
+ import Level._
+ protected var (lev, lib) = {
+ val p = java.util.regex.Pattern.compile("(error|warning|verbose|info)(\\,lib)?(.*)")
+ val m = p matcher level0
+ val (s, b) =
+ if (m.matches) (m.group(1), m.group(2) ne null)
+ else ("", false)
+ s match {
+ case "error" => (ERROR , b)
+ case "warning" => (WARNING, b)
+ case "verbose" => (VERBOSE, b)
+ case "info" => (INFO , b)
+ case _ => (SILENT , false)
+ }
+ }
+
+ def level = lev
+ def level_= (lev: Level) = { this.lev = lev }
+
+ private val tag0: String =
+ if (tag != null & tag.length > 0) tag+" " else ""
+
+ def info(msg: String) {
+ if (lev >= INFO) Console.println(tag0 + "(info): " + msg)
+ }
+
+ def verbose(msg: String) {
+ if (lev >= VERBOSE) Console.println(tag0 + "(verb): " + msg)
+ }
+
+ def warning(msg: String) {
+ if (lev >= WARNING) Console.err.println(tag0 + "(warn): " + msg)
+ }
+
+ def error(msg: String) {
+ if (lev >= ERROR) Console.err.println(tag0 + "(erro): " + msg)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RegistryDelegate.scala b/src/detach/library/scala/runtime/remoting/RegistryDelegate.scala
new file mode 100644
index 0000000000..ba6f6c042d
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RegistryDelegate.scala
@@ -0,0 +1,192 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RegistryDelegate.scala 18234 2009-07-07 13:21:57Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.{RMISecurityManager, Remote, RemoteException}
+import java.rmi.registry.{LocateRegistry, Registry}
+import java.rmi.server.UnicastRemoteObject
+
+/**
+ * <p>
+ * This class implements the registry delegate concept
+ * (see http://www.genady.net/rmi/v20/docs/delegate/RegistryDelegate.html)
+ * </p>
+ * <p>
+ * In order to enforce some level of security, the standard RMI registry
+ * implementation (e.g. <code>rmiregistry.exe</code>) only allows processes
+ * on the same host to register objects in the registry (think of a bank
+ * running a registry on one of its servers, and doesn't want anybody
+ * modifying it). So, by design, if a process tries to
+ * <code>bind(String, Remote)</code> an object to a remote registry,
+ * an exception will be thrown.
+ * </p>
+ * <p>
+ * However, the design of a distributed system may require remote clients to
+ * register themselves in a central registry. If such system is deployed in a
+ * controlled and trusted environment (e.g., a firewalled intranet with tight
+ * access control), the security risk may be acceptable.
+ * </p>
+ * <p>
+ * The simplest technical solution to the remote registration problem is to
+ * have a registry delegate. A registry delegate is an object that serves as
+ * a proxy for the real registry. The delegate itself usually appears in the
+ * registry under a well known name. It implements the Registry interface and
+ * simply delegates all method calls to the appropriate methods of the real
+ * registry. The delegate is allowed to perform bind and unbind operations
+ * because it is running on the same host as the registry.
+ * </p>
+ * <p>
+ * The common scenario for starting a registry and creating the delegate is
+ * starting a class with the following <code>main(Array[String])</code> method:
+ * </p>
+ * <pre>
+ * @throws(classOf[AccessException], classOf[RemoteException], classOf[AlreadyBoundException])
+ * <b>object</b> namingService {
+ * <b>def</b> main(args: Array[String]) {
+ * <b>if</b> (System.getSecurityManager() == <b>null</b>)
+ * System.setSecurityManager(<b>new</b> RMISecurityManager())
+ *
+ * <b>val</b> registry = LocateRegistry.createRegistry(REGISTRY_PORT)
+ * registry.bind(DELEGATE_NAME, <b>new</b> RegistryDelegate());
+ *
+ * do {
+ * <b>try</b> {
+ * Thread.sleep(Long.MAX_VALUE)
+ * } <b>catch</b> {
+ * <b>case</b> e: InterruptedException => // do nothing
+ * <b>case</b> e: Throwable => e.printStackTrace(); System.exit(1)
+ * }
+ * } while (<b>true</b>)
+ * }
+ * }</pre>
+ * <p>
+ * The common usage scenario looks something like:
+ * </p><pre>
+ * Registry remoteRegistry = LocateRegistry.getRegistry("remotehost.mycompany.com");
+ * Registry delegate = (Registry) remoteRegistry.lookup(DELEGATE_NAME);
+ * delegate.bind("someName", <b>new</b> SomeRemoteObject());</pre>
+ * <p>
+ * The <code>getRegistryDelegate(String)</code> method is a helper method
+ * that fetches the registry delegate for you.
+ * </p>
+ * <p>
+ * The <code>main(Array[String])</code> method of this class will create a
+ * local registry on the default port, create a registry delegate and bind
+ * it under the well known name that you chose in the wizard
+ * (<code>DELEGATE_NAME</code>).
+ * </p>
+ *
+ * @author Genady Beryozkin, rmi-info@genady.net
+ */
+
+object RMIDelegate {
+ /** The name under which the delegate appears in the registry. */
+ val DELEGATE_NAME = "foo"
+
+ /** This method retrieves the registry delegate from a registry that is
+ * running on a remote host.
+ */
+ @throws(classOf[RemoteException])
+ def getRegistryDelegate(remoteHost: String): Registry =
+ getRegistryDelegate(remoteHost, Registry.REGISTRY_PORT)
+
+ /** This method retrieves the registry delegate from a registry that is
+ * running on a remote host.
+ */
+ @throws(classOf[RemoteException])
+ def getRegistryDelegate(remoteHost: String, remotePort: Int): Registry = {
+ val registry = LocateRegistry.getRegistry(remoteHost, remotePort)
+ (registry lookup DELEGATE_NAME).asInstanceOf[Registry]
+ }
+
+ /** A simple way to run a registry and bind a registry delegate. */
+ @throws(classOf[RemoteException])
+ def main(args: Array[String]) {
+ var port = Registry.REGISTRY_PORT
+
+ if (args.length > 0) {
+ if (args(0) equals "-help") {
+ println("Usage: rmidelegate <options> <port>")
+ exit(0)
+ }
+ try {
+ port = args(0).toInt
+ } catch {
+ case e: NumberFormatException =>
+ println("Usage: rmidelegate <options> <port>")
+ exit(1)
+ }
+ val opts = args filter (_ startsWith "-J-D")
+ for (opt <- opts) {
+ val x = opt.substring(4) split "="
+ if (x.length == 2) System.setProperty(x(0), x(1))
+ else System.setProperty(x(0), "")
+ }
+ }
+
+ if (System.getSecurityManager() == null)
+ System.setSecurityManager(new RMISecurityManager() {
+ override def checkPermission(p: java.security.Permission) {}
+ })
+
+
+ val registry = LocateRegistry.createRegistry(port)
+ registry.bind(DELEGATE_NAME, new RegistryDelegate())
+
+ do {
+ try {
+ Thread.sleep(Long.MaxValue)
+ } catch {
+ case e: InterruptedException =>
+ // do nothing
+ case e: Throwable =>
+ e.printStackTrace()
+ exit(1)
+ }
+ } while (true)
+ }
+
+}
+
+/** Create a delegate for a user provided registry instance. The registry is
+ * assumed to be a local registry, as there is no point in creating a delegate
+ * for a remote registry.
+ */
+class RegistryDelegate(reg: Registry) extends UnicastRemoteObject with Registry {
+ /** The local registry */
+ private val localRegistry: Registry = reg
+
+ /** Create a delegate for a local registry that is bound to the default
+ * local port (1099).
+ */
+ def this() = this(LocateRegistry.getRegistry())
+
+ /** Create a delegate for a local registry that is bound to a user
+ * specified port.
+ */
+ def this(port: Int) = this(LocateRegistry.getRegistry(port))
+
+ @throws(classOf[RemoteException])
+ def bind(name: String, obj: Remote) { localRegistry.bind(name, obj) }
+
+ @throws(classOf[RemoteException])
+ def list(): Array[String] = localRegistry.list()
+
+ @throws(classOf[RemoteException])
+ def lookup(name: String): Remote = localRegistry.lookup(name)
+
+ @throws(classOf[RemoteException])
+ def rebind(name: String, obj: Remote) { localRegistry.rebind(name, obj) }
+
+ @throws(classOf[RemoteException])
+ def unbind(name: String) { localRegistry.unbind(name) }
+
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteBooleanRef.scala b/src/detach/library/scala/runtime/remoting/RemoteBooleanRef.scala
new file mode 100644
index 0000000000..be5597fa23
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteBooleanRef.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteBooleanRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{BooleanRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteBooleanRef</code> provides a remote interface
+ * for manipulating boolean references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteBooleanRef {
+ def elem_=(value: Boolean)
+ def elem: Boolean
+}
+
+/**
+ * The class <code>RemoteBooleanRefImpl</code> implements a remote (global)
+ * boolean reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.BooleanRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface to automatically
+ * remove the no more referenced binding from the registry.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteBooleanRefImpl(name: String, x: BooleanRef)
+extends UnicastRemoteObject with RemoteBooleanRef with Unreferenced {
+ def elem_=(value: Boolean) { x.elem = value }
+ def elem: Boolean = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteBooleanRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteByteRef.scala b/src/detach/library/scala/runtime/remoting/RemoteByteRef.scala
new file mode 100644
index 0000000000..cac0ceb260
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteByteRef.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteByteRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{ByteRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteByteRef</code> provides a remote interface
+ * for manipulating byte references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteByteRef {
+ def elem_=(value: Byte)
+ def elem: Byte
+}
+
+/**
+ * The class <code>RemoteByteRefImpl</code> implements a remote (global)
+ * byte reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.ByteRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface to automatically
+ * remove the no more referenced binding from the registry.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteByteRefImpl(name: String, x: ByteRef)
+extends UnicastRemoteObject with RemoteByteRef with Unreferenced {
+ def elem_=(value: Byte) { x.elem = value }
+ def elem: Byte = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteByteRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteCharRef.scala b/src/detach/library/scala/runtime/remoting/RemoteCharRef.scala
new file mode 100644
index 0000000000..9b00c8c1db
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteCharRef.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteCharRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{CharRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteCharRef</code> provides a remote interface
+ * for manipulating character references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteCharRef {
+ def elem_=(value: Char)
+ def elem: Char
+}
+
+/**
+ * The class <code>RemoteCharRefImpl</code> implements a remote (global)
+ * character reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.CharRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface to automatically
+ * remove the no more referenced binding from the registry.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteCharRefImpl(name: String, x: CharRef)
+extends UnicastRemoteObject with RemoteCharRef with Unreferenced {
+ def elem_=(value: Char) { x.elem = value }
+ def elem: Char = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteCharRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteDoubleRef.scala b/src/detach/library/scala/runtime/remoting/RemoteDoubleRef.scala
new file mode 100644
index 0000000000..bdbcd398bd
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteDoubleRef.scala
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteDoubleRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{DoubleRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteDoubleRef</code> provides..
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteDoubleRef {
+ def elem_=(value: Double)
+ def elem: Double
+}
+
+/**
+ * The class <code>RemoteDoubleRefImpl</code> implements a remote (global)
+ * double reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.DoubleRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface to automatically
+ * remove the no more referenced binding from the registry.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteDoubleRefImpl(name: String, x: DoubleRef)
+extends UnicastRemoteObject with RemoteDoubleRef with Unreferenced {
+ def elem_=(value: Double) { x.elem = value }
+ def elem: Double = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteDoubleRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteFloatRef.scala b/src/detach/library/scala/runtime/remoting/RemoteFloatRef.scala
new file mode 100644
index 0000000000..158894bc18
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteFloatRef.scala
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteFloatRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{FloatRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteFloatRef</code> provides a remote interface
+ * for manipulating float references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteFloatRef {
+ def elem_=(value: Float)
+ def elem: Float
+}
+
+/**
+ * The class <code>RemoteFloatRefImpl</code> implements a remote (global)
+ * float reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.FloatRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteFloatRefImpl(name: String, x: FloatRef)
+extends UnicastRemoteObject with RemoteFloatRef with Unreferenced {
+ def elem_=(value: Float) { x.elem = value }
+ def elem: Float = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteIntFloatImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteGC.scala b/src/detach/library/scala/runtime/remoting/RemoteGC.scala
new file mode 100644
index 0000000000..d4a5108cb8
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteGC.scala
@@ -0,0 +1,67 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteGC.scala 17547 2009-04-21 13:56:28Z michelou $
+
+package scala.runtime.remoting
+
+import java.lang.ref.{Reference, WeakReference, ReferenceQueue}
+import java.rmi.{NoSuchObjectException, Remote}
+import java.rmi.server.UnicastRemoteObject
+
+import scala.collection.mutable.HashSet
+
+/**
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+// Adapted from scala.actors.ActorGC
+private [runtime] class RemoteGC {
+
+ private val refQueue = new ReferenceQueue[Remote]
+ private val refSet = new HashSet[Reference[T] forSome { type T <: Remote }]
+
+ private var liveRefs = 0
+
+ def newRef(a: Remote) = synchronized {
+ refSet += new WeakReference(a, refQueue)
+ liveRefs += 1
+ info("added object reference \""+a+"\" ("+liveRefs+")")
+ }
+
+ def gc() = synchronized {
+ info("GC called ("+liveRefs+")")
+ // check for unreachable object references
+ def drain() {
+ val wr = refQueue.poll
+ if (wr != null) {
+ val msg = try {
+ UnicastRemoteObject.unexportObject(wr.get, true/*force*/)
+ "removed object reference"
+ }
+ catch {
+ case e: NoSuchObjectException =>
+ "object already unbound"
+ }
+ info(msg+" ("+liveRefs+")")
+ liveRefs -= 1
+ refSet -= wr
+ // continue draining
+ drain()
+ }
+ }
+ drain()
+ }
+
+ def allClosed: Boolean = synchronized {
+ liveRefs <= 0
+ }
+
+ private def info(msg: String) { Debug.info("[RemoteGC] "+msg) }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteIntRef.scala b/src/detach/library/scala/runtime/remoting/RemoteIntRef.scala
new file mode 100644
index 0000000000..211a7db971
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteIntRef.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteIntRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{IntRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteIntRef</code> provides a remote interface
+ * for manipulating integer references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteIntRef {
+ def elem_=(value: Int)
+ def elem: Int
+}
+
+/**
+ * The class <code>RemoteIntRefImpl</code> implements a remote (global)
+ * integer reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.IntRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface to automatically
+ * remove the no more referenced binding from the registry.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteIntRefImpl(name: String, x: IntRef)
+extends UnicastRemoteObject with RemoteIntRef with Unreferenced {
+ def elem_=(value: Int) { x.elem = value }
+ def elem: Int = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteIntRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteLongRef.scala b/src/detach/library/scala/runtime/remoting/RemoteLongRef.scala
new file mode 100644
index 0000000000..469bb534ed
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteLongRef.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteLongRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{LongRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteLongRef</code> provides a remote interface
+ * for manipulating long integer references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteLongRef {
+ def elem_=(value: Long)
+ def elem: Long
+}
+
+/**
+ * The class <code>RemoteLongRefImpl</code> implements a remote (global)
+ * long integer reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.LongRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface to automatically
+ * remove the no more referenced binding from the registry.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteLongRefImpl(name: String, x: LongRef)
+extends UnicastRemoteObject with RemoteLongRef with Unreferenced {
+ def elem_=(value: Long) { x.elem = value }
+ def elem: Long = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteLongRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteObjectRef.scala b/src/detach/library/scala/runtime/remoting/RemoteObjectRef.scala
new file mode 100644
index 0000000000..c5c6989618
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteObjectRef.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteObjectRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{ObjectRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteObjectRef</code> provides a remote interface
+ * for manipulating object references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteObjectRef {
+ def elem_=(value: AnyRef)
+ def elem: AnyRef
+}
+
+/**
+ * The class <code>RemoteObjectRefImpl</code> implements a remote (global)
+ * object reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.ObjectRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface to automatically
+ * remove the no more referenced binding from the registry.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteObjectRefImpl(name: String, x: ObjectRef)
+extends UnicastRemoteObject with RemoteObjectRef with Unreferenced {
+ def elem_=(value: AnyRef) { x.elem = value }
+ def elem: AnyRef = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteObjectRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}
diff --git a/src/detach/library/scala/runtime/remoting/RemoteShortRef.scala b/src/detach/library/scala/runtime/remoting/RemoteShortRef.scala
new file mode 100644
index 0000000000..bc94d79b9c
--- /dev/null
+++ b/src/detach/library/scala/runtime/remoting/RemoteShortRef.scala
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: RemoteShortRef.scala 18398 2009-07-28 14:26:36Z michelou $
+
+package scala.runtime.remoting
+
+import java.rmi.server.{UnicastRemoteObject, Unreferenced}
+import scala.runtime.{ShortRef, RemoteRef}
+
+/**
+ * The trait Remote<code>RemoteShortRef</code> provides a remote interface
+ * for manipulating short integer references.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+@remote
+trait RemoteShortRef {
+ def elem_=(value: Short)
+ def elem: Short
+}
+
+/**
+ * The class <code>RemoteShortRefImpl</code> implements a remote (global)
+ * short integer reference by inheriting from the class
+ * <code>UnicastRemoteObject</code>.
+ *
+ * In particular, it forwards method invocations to the <code>elem</code>
+ * accessors of class <code>runtime.ShortRef</code> and implements the
+ * <code>java.rmi.server.Unreferenced</code> interface.
+ *
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+class RemoteShortRefImpl(name: String, x: ShortRef)
+extends UnicastRemoteObject with RemoteShortRef with Unreferenced {
+ def elem_=(value: Short) { x.elem = value }
+ def elem: Short = x.elem
+ override def toString() = x.elem.toString
+ def unreferenced() {
+ Debug.info("[RemoteShortRefImpl] unreferenced: "+this)
+ RemoteRef.unbind(name)
+ }
+}