diff options
author | michelou <michelou@epfl.ch> | 2010-11-17 12:26:13 +0000 |
---|---|---|
committer | michelou <michelou@epfl.ch> | 2010-11-17 12:26:13 +0000 |
commit | c09f6173e96ec741c9b38edfee969ae8c6b74d4e (patch) | |
tree | 1f06579f72afa12092acd0b5bbb7c678291cf619 /src/detach/library | |
parent | 363a1456f671323b35dcacf2c8b8eb39180b8a53 (diff) | |
download | scala-c09f6173e96ec741c9b38edfee969ae8c6b74d4e.tar.gz scala-c09f6173e96ec741c9b38edfee969ae8c6b74d4e.tar.bz2 scala-c09f6173e96ec741c9b38edfee969ae8c6b74d4e.zip |
updates Scala examples, added detach plugin
Diffstat (limited to 'src/detach/library')
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<primtype></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) + } +} |