updates Scala examples, added detach plugin

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@23531 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
michelou 2010-11-17 12:26:13 +00:00
parent 00da152c72
commit b192503851
43 changed files with 3580 additions and 14 deletions

186
build.detach.xml Normal file
View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="sabbus" default="build">
<description>
SuperSabbus for Scala detach plugin.
</description>
<echo level="info" message="Running SABBUS for ${ant.project.name}..."/>
<!-- ===========================================================================
END-USER TARGETS
============================================================================ -->
<target name="build" depends="pack.done"
description="Builds the Scala detach plugin."/>
<target name="clean" depends="quick.clean">
</target>
<target name="all.clean" depends="quick.clean, pack.clean">
</target>
<!-- ===========================================================================
PROPERTIES
============================================================================ -->
<property environment="env"/>
<!-- Prevents system classpath from being used -->
<property name="build.sysclasspath" value="ignore"/>
<!-- Defines the repository layout -->
<property name="lib.dir" value="${basedir}/lib"/>
<property name="src.dir" value="${basedir}/src"/>
<property name="partest.dir" value="${basedir}/test"/>
<!-- Loads custom properties definitions -->
<property file="${basedir}/build.properties"/>
<!-- Sets location of build folders -->
<property name="build.dir" value="${basedir}/build"/>
<property name="build-quick.dir" value="${build.dir}/quick"/>
<property name="build-pack.dir" value="${build.dir}/pack"/>
<!-- if ANT_OPTS is already set by the environment, it will be unaltered,
but if it is unset it will take this default value. -->
<property name="env.ANT_OPTS" value="-Xms1024M -Xmx1024M -Xss1M -XX:MaxPermSize=128M -XX:+UseParallelGC" />
<property
name="scalacfork.jvmargs"
value="${env.ANT_OPTS}"/>
<property name="scalac.args.quick" value="-deprecation"/>
<property name="scalac.args.optimise" value=""/>
<!-- Setting-up Ant contrib tasks -->
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant/ant-contrib.jar"/>
<!-- ===========================================================================
QUICK BUILD (QUICK)
============================================================================ -->
<target name="quick.clean">
<delete includeemptydirs="yes" quiet="yes" failonerror="no">
<fileset dir="${build-quick.dir}/classes/detach-library"/>
<fileset dir="${build-quick.dir}/classes/detach-plugin"/>
</delete>
</target>
<target name="quick.done">
<stopwatch name="quick.done.timer"/>
<path id="quick.classpath">
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
<pathelement location="${lib.dir}/fjbg.jar"/>
<pathelement location="${lib.dir}/msil.jar"/>
<pathelement location="${lib.dir}/forkjoin.jar"/>
<pathelement location="${ant.home}/lib/ant.jar"/>
</path>
<taskdef
resource="scala/tools/ant/sabbus/antlib.xml"
classpathref="quick.classpath"
/>
<mkdir dir="${build-quick.dir}/classes/detach-plugin"/>
<scalacfork
destdir="${build-quick.dir}/classes/detach-plugin"
compilerpathref="quick.classpath"
params="${scalac.args.quick}"
srcdir="${src.dir}/detach/plugin"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
<compilationpath>
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
<pathelement location="${build-quick.dir}/classes/detach-plugin"/>
<pathelement location="${lib.dir}/forkjoin.jar"/>
</compilationpath>
</scalacfork>
<copy
file="${src.dir}/detach/plugin/scalac-plugin.xml"
todir="${build-quick.dir}/classes/detach-plugin"
/>
<mkdir dir="${build-quick.dir}/classes/detach-library"/>
<scalacfork
destdir="${build-quick.dir}/classes/detach-library"
compilerpathref="quick.classpath"
params="${scalac.args.quick}"
srcdir="${src.dir}/detach/library"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
<compilationpath>
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${lib.dir}/forkjoin.jar"/>
</compilationpath>
</scalacfork>
<touch file="${build-quick.dir}/plugins.complete" verbose="no"/>
<stopwatch name="quick.done.timer" action="total"/>
</target>
<!-- ===========================================================================
PACKED QUICK BUILD (PACK)
============================================================================ -->
<target name="pack.start" depends="quick.done"/>
<target name="pack.pre-lib" depends="pack.start">
<uptodate
property="pack.lib.available"
targetfile="${build-pack.dir}/lib/scala-detach.jar"
srcfile="${build-quick.dir}/plugins.complete"/>
</target>
<target name="pack.lib" depends="pack.pre-lib" unless="pack.lib.available">
<mkdir dir="${build-pack.dir}/misc/scala-devel/plugins"/>
<jar destfile="${build-pack.dir}/misc/scala-devel/plugins/detach.jar">
<fileset dir="${build-quick.dir}/classes/detach-plugin"/>
</jar>
<mkdir dir="${build-pack.dir}/lib"/>
<jar destfile="${build-pack.dir}/lib/scala-detach.jar">
<fileset dir="${build-quick.dir}/classes/detach-library">
<include name="scala/**"/>
</fileset>
</jar>
</target>
<target name="pack.done" depends="pack.lib">
<path id="pack.classpath">
<pathelement location="${build-pack.dir}/lib/scala-library.jar"/>
<pathelement location="${build-pack.dir}/lib/scala-compiler.jar"/>
<pathelement location="${build-pack.dir}/lib/scala-detach.jar"/>
<pathelement location="${build-pack.dir}/lib/scala-partest.jar"/>
<pathelement location="${build-pack.dir}/lib/scalap.jar"/>
<pathelement location="${ant.home}/lib/ant.jar"/>
<pathelement location="${lib.dir}/jline.jar"/>
</path>
<taskdef resource="scala/tools/ant/antlib.xml" classpathref="pack.classpath"/>
<taskdef resource="scala/tools/partest/antlib.xml" classpathref="pack.classpath"/>
</target>
<target name="pack.clean">
<delete includeemptydirs="yes" quiet="yes" failonerror="no">
<fileset dir="${build-pack.dir}/lib" includes="scala-detach.jar"/>
<fileset dir="${build-pack.dir}/misc/scala-devel/plugins" includes="detach.jar"/>
</delete>
</target>
<!-- ===========================================================================
TEST SUITE
============================================================================ -->
<target name="test.suite" depends="pack.done">
<property name="partest.srcdir" value="files" />
<partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
timeout="2400000"
srcdir="${partest.srcdir}"
scalacopts="${scalac.args.optimise} -Xpluginsdir ${build-pack.dir}/misc/scala-devel/plugins -Xplugin-require:detach -P:detach:enable">
<compilationpath>
<path refid="pack.classpath"/>
<fileset dir="${partest.dir}/files/lib" includes="*.jar" />
</compilationpath>
<negtests dir="${partest.dir}/${partest.srcdir}/detach-neg" includes="*.scala"/>
<runtests dir="${partest.dir}/${partest.srcdir}/detach-run" includes="*.scala"/>
</partest>
</target>
</project>

View File

@ -30,6 +30,8 @@ PROPERTIES
<property name="scala.comp.jar" value="${lib.dir}/scala-compiler.jar"/> <property name="scala.comp.jar" value="${lib.dir}/scala-compiler.jar"/>
<property name="fjbg.name" value="fjbg.jar"/> <property name="fjbg.name" value="fjbg.jar"/>
<property name="fjbg.jar" value="${lib.dir}/${fjbg.name}"/> <property name="fjbg.jar" value="${lib.dir}/${fjbg.name}"/>
<property name="msil.name" value="msil.jar"/>
<property name="msil.jar" value="${lib.dir}/${msil.name}"/>
<property name="ant.jar" value="${ant.home}/lib/ant.jar"/> <property name="ant.jar" value="${ant.home}/lib/ant.jar"/>
<property name="ant-contrib.jar" value="${lib.dir}/ant/ant-contrib.jar"/> <property name="ant-contrib.jar" value="${lib.dir}/ant/ant-contrib.jar"/>
<!-- --> <!-- -->
@ -61,7 +63,7 @@ INITIALISATION
classpath="${scala.lib.jar}" classpath="${scala.lib.jar}"
/> />
<available <available
classname="scala.List" classname="scala.collection.immutable.List"
classpath="${scala.lib.jar}" classpath="${scala.lib.jar}"
/> />
<available <available
@ -88,6 +90,15 @@ INITIALISATION
/> />
</not></condition> </not></condition>
</fail> </fail>
<echo level="verbose" message="msil.jar=${msil.jar}"/>
<fail message="MSIL library in '${lib.dir}/' is not available">
<condition><not>
<available
classname="ch.epfl.lamp.compiler.msil.MemberInfo"
classpath="${msil.jar}"
/>
</not></condition>
</fail>
<echo level="verbose" message="ant.jar=${ant.jar}"/> <echo level="verbose" message="ant.jar=${ant.jar}"/>
<echo level="verbose" message="ant-contrib.jar=${ant-contrib.jar}"/> <echo level="verbose" message="ant-contrib.jar=${ant-contrib.jar}"/>
<fail message="Additional Ant tasks in '${lib.dir}/' is not available"> <fail message="Additional Ant tasks in '${lib.dir}/' is not available">
@ -101,6 +112,7 @@ INITIALISATION
<!-- Creating class-pathes --> <!-- Creating class-pathes -->
<path id="common.classpath"> <path id="common.classpath">
<pathelement location="${fjbg.jar}"/> <pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
</path> </path>
<path id="scala.classpath"> <path id="scala.classpath">
<pathelement location="${scala.lib.jar}"/> <pathelement location="${scala.lib.jar}"/>
@ -202,7 +214,7 @@ BUILD
<for list="${list}" param="file"> <for list="${list}" param="file">
<sequential> <sequential>
<scalac srcdir="${src.dir}" <scalac srcdir="${src.dir}"
destdir="${build.dir}"> destdir="${build.dir}" deprecation="true">
<classpath> <classpath>
<pathelement location="${scala.lib.jar}"/> <pathelement location="${scala.lib.jar}"/>
<pathelement location="${build.dir}"/> <pathelement location="${build.dir}"/>

View File

@ -4,19 +4,19 @@ object boundedbuffer {
import concurrent.ops._ import concurrent.ops._
class BoundedBuffer[a](N: Int) { class BoundedBuffer[A](N: Int)(implicit m: ClassManifest[A]) {
var in, out, n = 0 var in, out, n = 0
val elems = new Array[a](N) val elems = new Array[A](N)
def await(cond: => Boolean) = while (!cond) { wait() } def await(cond: => Boolean) = while (!cond) { wait() }
def put(x: a) = synchronized { def put(x: A) = synchronized {
await (n < N) await (n < N)
elems(in) = x; in = (in + 1) % N; n += 1 elems(in) = x; in = (in + 1) % N; n += 1
if (n == 1) notifyAll() if (n == 1) notifyAll()
} }
def get: a = synchronized { def get: A = synchronized {
await (n != 0) await (n != 0)
val x = elems(out); out = (out + 1) % N ; n -= 1 val x = elems(out); out = (out + 1) % N ; n -= 1
if (n == N - 1) notifyAll() if (n == N - 1) notifyAll()

View File

@ -3,10 +3,10 @@ package examples
object gadts extends Application { object gadts extends Application {
abstract class Term[T] abstract class Term[T]
case class Lit(x: int) extends Term[int] case class Lit(x: Int) extends Term[Int]
case class Succ(t: Term[int]) extends Term[int] case class Succ(t: Term[Int]) extends Term[Int]
case class IsZero(t: Term[int]) extends Term[boolean] case class IsZero(t: Term[Int]) extends Term[Boolean]
case class If[T](c: Term[boolean], case class If[T](c: Term[Boolean],
t1: Term[T], t1: Term[T],
t2: Term[T]) extends Term[T] t2: Term[T]) extends Term[T]
@ -16,7 +16,7 @@ object gadts extends Application {
case IsZero(u) => eval(u) == 0 case IsZero(u) => eval(u) == 0
case If(c, u1, u2) => eval(if (eval(c)) u1 else u2) case If(c, u1, u2) => eval(if (eval(c)) u1 else u2)
} }
Console.println( println(
eval(If(IsZero(Lit(1)), Lit(41), Succ(Lit(41))))) eval(If(IsZero(Lit(1)), Lit(41), Succ(Lit(41)))))
} }

View File

@ -10,10 +10,10 @@ object iterators {
} }
def printArray(xs: Array[Double]) = def printArray(xs: Array[Double]) =
Iterator.fromArray(xs) foreach { x => println(x) } xs.iterator foreach { x => println(x) }
def findGreater(xs: Array[Double], limit: Double) = def findGreater(xs: Array[Double], limit: Double) =
Iterator.fromArray(xs) xs.iterator
.zip(Iterator.from(0)) .zip(Iterator.from(0))
.filter{case Pair(x, i) => x > limit } .filter{case Pair(x, i) => x > limit }
.map{case Pair(x, i) => i} .map{case Pair(x, i) => i}

View File

@ -112,7 +112,6 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
val noCompletion = BooleanSetting ("-Yno-completion", "Disable tab-completion in the REPL") val noCompletion = BooleanSetting ("-Yno-completion", "Disable tab-completion in the REPL")
val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination") val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination")
val debug = BooleanSetting ("-Ydebug", "Output debugging messages") val debug = BooleanSetting ("-Ydebug", "Output debugging messages")
val Xdetach = BooleanSetting ("-Ydetach", "Perform detaching of remote closures")
// val doc = BooleanSetting ("-Ydoc", "Generate documentation") // val doc = BooleanSetting ("-Ydoc", "Generate documentation")
val inline = BooleanSetting ("-Yinline", "Perform inlining when possible") val inline = BooleanSetting ("-Yinline", "Perform inlining when possible")
val Xlinearizer = ChoiceSetting ("-Ylinearizer", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo") . val Xlinearizer = ChoiceSetting ("-Ylinearizer", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo") .

View File

@ -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)

View File

@ -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('['))
}
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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) }
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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) }
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
/* NSC -- new Scala compiler
* Copyright 2005-2010 LAMP/EPFL
* @author Stephane Micheloud
*/
package scala.tools.detach
import scala.tools.nsc.{Global, Phase}
import scala.tools.nsc.plugins.{Plugin, PluginComponent}
class DetachPlugin(val global: Global) extends Plugin {
import global._
val name = "detach"
val description = "Perform detaching of remote closures"
object detach extends {
val global = DetachPlugin.this.global
val runsAfter = List("lambdalift")
override val runsBefore = List("constructors")
} with Detach
val components = List[PluginComponent](detach)
def setEnabled(flag: Boolean) { detach.isEnabled = flag }
override def processOptions(options: List[String], error: String => Unit) = {
var enabled = false
for (option <- options) {
if (option == "enable") {
enabled = true
} else {
error("Option not understood: "+option)
}
}
setEnabled(enabled)
}
override val optionsHelp: Option[String] =
Some(" -P:detach:enable Enable detaching of remote closures")
}

View File

@ -0,0 +1,4 @@
<plugin>
<name>detach</name>
<classname>scala.tools.detach.DetachPlugin</classname>
</plugin>

View File

@ -0,0 +1,4 @@
det_bar.scala:7: error: detach inapplicable for method bar
detach(bar)
^
one error found

View File

@ -0,0 +1,13 @@
import scala.remoting._
class A(y: Int) {
var z = 2
var bar = (x: Int) => x + y + z
def foo(x: Int): Int = x + y + z
bar = (x: Int) => x * y
detach(bar)
}
object test extends Application {
val a = new A(1)
println(a.bar(2))
}

View File

@ -0,0 +1,5 @@
Server.main 8889
Client.main 127.0.0.1 8889
yInstVal = 10
zLocVal = 1000
result received: 11111

View File

@ -0,0 +1,50 @@
import scala.actors.Actor._, ClientHelper._
import scala.actors.remote._, RemoteActor._
import scala.remoting._, Debug._
object Foo {
def trace(msg: String) { info("[Foo.trace] "+msg)}
}
object Client {
val yInstVal: Int = 10
var yInstVar: Int = 99
object Bar {
def trace(msg: String) { info("[Bar.trace] "+msg) }
}
def main(args: Array[String]) {
init(args)
actor {
val server = select(Node(host, port), 'Server)
val zLocVal: Int = 1000
var zLocVar: Int = 9998
server ! detach(
(x: Int) => {
println("yInstVal = "+yInstVal)
this.trace("yInstVar = "+yInstVar)
Bar.trace("zLocVal = "+zLocVal)
Foo.trace("zLocVar = "+zLocVar)
zLocVar += 2
System.out.println("zLocVal = "+zLocVal)
Debug.info("zLocVar = "+zLocVar)
x + yInstVal + yInstVar + zLocVal + zLocVar
})
react {
case result: Int =>
println("result received: " + result)
Predef.exit(0)
}
}
}
private def trace(msg: String) { info("[Client.trace] "+msg) }
}
object ClientHelper {
private var _host = "127.0.0.1"
private var _port = 8888
def host = _host
def port = _port
def init(args: Array[String]) {
try { _host = args(0) } catch { case _ => }
try { _port = args(1).toInt } catch { case _ => }
}
}

View File

@ -0,0 +1,24 @@
import scala.actors._, Actor._
import scala.actors.remote._, RemoteActor._
import scala.reflect.Manifest
object Server extends ServerConsole {
private def computation(f: Int => Int): Int = {
//some time-consuming task
f(2)
}
def main(args: Array[String]) {
actor {
classLoader = serverClassLoader
alive(args(0).toInt)
register('Server, self)
loopWhile(isRunning) {
react {
case f: (Int => Int) =>
val result = computation(f)
sender ! result
}
}
}
}
}

View File

@ -0,0 +1,154 @@
import java.io._
import java.net.{JarURLConnection, URL, URLClassLoader}
import scala.remoting.Debug
private class ServerObjectInputStream(in: InputStream, cl: ClassLoader)
extends ObjectInputStream(in) {
override def resolveClass(cd: ObjectStreamClass): Class[_] = {
println("[ServerObjectInputStream] resolveClass "+cd.getName)
try {
Debug.info("load class "+cd.getName+" from "+cl)
val c = cl.loadClass(cd.getName)
Debug.info("loaded class "+c.getName)
c
} catch {
case cnf: ClassNotFoundException =>
Debug.info("resolve class (this) "+cd.getName)
val c = super.resolveClass(cd)
Debug.info("resolve class (super) "+c.getName)
c
}
}
override def resolveProxyClass(interfaces: Array[String]): Class[_] = {
println("[ServerObjectInputStream] resolveProxyClass "+interfaces.toList)
try {
val c = cl.loadClass(interfaces.last)
Debug.info("loaded class "+c.getName)
c
} catch {
case cnf: ClassNotFoundException =>
Debug.info("resolve proxy class (this) "+interfaces.last)
val c = super.resolveProxyClass(interfaces)
Debug.info("resolve proxy class (super) "+c.getName)
c
}
}
}
/*
// VARIANT 1
class ServerClassLoader extends URLClassLoader(urls) {
import scala.reflect.Manifest
def load[A](a: Array[Byte])(implicit expected: Manifest[A]): A = {
val in = new ServerObjectInputStream(new ByteArrayInputStream(a), this)
val found = in.readObject.asInstanceOf[Manifest[_]]
if (! (found <:< expected))
throw new ClassCastException("type mismatch;"+
"\n found : "+found+
"\n required: "+expected)
val o = in.readObject.asInstanceOf[A]
in.close()
o
}
override def findClass(name: String): Class[_] = {
println("[ServerClassLoader] findClass "+name)
val b = loadClassData(name)
if (b != null) defineClass(name, b, 0, b.length)
else super.findClass(name)
}
private def loadClassData(name: String): Array[Byte] = {
println("[ServerClassLoader] loadClassData "+name)
null
}
}
val serverClassLoader = new ServerClassLoader
*/
/*
class ServerClassLoader(parent: ClassLoader) extends URLClassLoader(urls, parent) {
import scala.reflect.Manifest
def load[A](a: Array[Byte])(implicit expected: Manifest[A]): A = {
val in = new ServerObjectInputStream(new ByteArrayInputStream(a), this)
val found = in.readObject.asInstanceOf[Manifest[_]]
if (! (found <:< expected))
throw new ClassCastException("type mismatch;"+
"\n found : "+found+
"\n required: "+expected)
val o = in.readObject.asInstanceOf[A]
in.close()
o
}
override def findClass(name: String): Class[_] = {
println("[ServerClassLoader] findClass "+name)
val b = loadClassData(name)
if (b != null) defineClass(name, b, 0, b.length)
else super.findClass(name)
}
private def loadClassData(name: String): Array[Byte] = {
println("[ServerClassLoader] loadClassData "+name)
null
}
}
*/
class ServerClassLoader(urls: Array[URL], parent: ClassLoader)
extends URLClassLoader(urls, parent) {
private val cache = new collection.mutable.HashMap[String, Class[_]]
for (url <- urls) {
val jarurl = new URL("jar:"+url+"!/")
val con = jarurl.openConnection().asInstanceOf[JarURLConnection]
val jar = con.getJarFile
val e = jar.entries
while (e.hasMoreElements) {
val ze = e.nextElement
val path = ze.getName
if (path endsWith ".class") {
val size = ze.getSize
val name = path.replace("/", ".").substring(0, path.length - 6)
cache += name -> this.loadClass(name)
println("[ServerClassLoader] added "+name+" ("+size+")")
}
}; //jar.close()
}
override def findClass(name: String): Class[_] = {
println("[ServerClassLoader] findClass: name="+name)
cache get name match {
case Some(cl) =>
println(name+" cached"); cl
case None =>
println(name+" not cached"); super.findClass(name)
}
}
}
/*
try {
JarFile jarFile = new JarFile(srcPath);
Enumeration<JarEntry> entries = jarFile.entries();
String url = "file:" + srcPath;
System.out.println(url);
URLClassLoader classLoader = new URLClassLoader(
new URL[] { new URL(url) });
while (entries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) entries
.nextElement();
String classPath = jarEntry.getName();
if (classPath.endsWith(".class")) {
String className = classPath.replace("/", ".")
.substring(0, classPath.length() - 6);
try {
Class clazz = classLoader
.loadClass(className);
//Et , tu fais ce que tu vexu avec la classe
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
*/

View File

@ -0,0 +1,71 @@
import java.io._
import scala.compat.Platform.currentTime
import scala.remoting.Debug, Debug._
trait ServerConsole extends Thread {
private val startTime = currentTime
actors.Debug.level = // e.g. 3 // info+warning+error
try { System.getProperty("scala.actors.logLevel", "0").toInt }
catch { case e => 0 }
start()
val serverClassLoader = {
import java.rmi.server.RMIClassLoader
val codebase = System.getProperty("java.rmi.server.codebase")
info("[ServerConsole] codebase="+codebase)
RMIClassLoader.getClassLoader(codebase)
}
private var isTerminated = false
def terminate() { isTerminated = false }
def isRunning = !isTerminated
override def run() {
val in = new BufferedReader(new InputStreamReader(System.in))
var quit = false
while (!quit) {
val args = getArgs(in)
if (args contains "quit")
quit = true
if (args contains "cls") {
println(ERASE_SCREEN)
println(CURSOR_HOME)
}
if (args contains "warning")
Debug.level = Level.WARNING
if (args contains "info")
Debug.level = Level.INFO
if (args contains "silent")
Debug.level = Level.SILENT
}
terminate()
println("Server exited ("+mkTimeString(currentTime - startTime)+")")
exit(0)
}
protected def trace(msg: String) {
Debug.info("[ServerConsole.trace] "+msg)
}
private def getArgs(in: BufferedReader): List[String] = {
val input = try { in.readLine() } catch { case _ => null }
if (input != null) (input.trim split "\\s+").toList else Nil
}
private def mkTimeString(time: Long): String = {
def twoDigits(i: Long) = (if (i < 10) "0" else "")+i
val sec = time / 1000
val min = sec / 60
val h = min / 60
twoDigits(h) +":"+
twoDigits(min - h * 60)+":"+
twoDigits(sec - min * 60)
}
private val ERASE_SCREEN = "\033[2J"
private val CURSOR_HOME = "\033[H"
}

View File

@ -0,0 +1 @@
-Xpluginsdir ../../../../build/pack/misc/scala-devel/plugins -Xplugin-require:detach -P:detach:enable

View File

@ -0,0 +1,140 @@
object Test {
val actors_logLevel = "0"
// = "3" // info+warning+error
val logLevel = "silent"
// = "info" // debug user code only
// = "info,lib" // debug user & library code
// we assume an Apache server is running locally for deployment
private val sep = java.io.File.separator
val docPath = System.getProperty("user.home")+sep+"public_html"
val docRoot = "http://127.0.0.1/~"+System.getProperty("user.name")
val host = "127.0.0.1"
val port = 8889
def main(args: Array[String]) {
setenv()
println("Server.main "+port)
Server.main(Array(port.toString))
println("Client.main "+host+" "+port)
Client.main(Array(host, port.toString))
Server.terminate()
}
private def setenv() {
import java.io._, java.util.jar._
val policyTmpl =
System.getProperty("partest.cwd")+sep+"actor"+sep+"java.policy"
val outPath = System.getProperty("partest.output")
val libPath = System.getProperty("partest.lib")
val policyFile = outPath+sep+"java.policy"
val codebaseDir = outPath+sep+"-"
assert((new java.io.File(docPath)).isDirectory,
"Root directory \""+docPath+"\" not found")
val deployJar = docPath+sep+"actor_deploy.jar"
val deployUrl = docRoot+"/actor_deploy.jar"
// Java properties for server & client
System.setProperty("scala.actors.logLevel", actors_logLevel)
System.setProperty("scala.remoting.logLevel", logLevel)
System.setProperty("java.security.manager", "")
System.setProperty("java.security.policy", policyFile)
// Java properties for server only
System.setProperty("java.rmi.server.codebase", deployUrl)
System.setProperty("java.rmi.server.hostname", host)
System.setProperty("java.rmi.server.useCodebaseOnly", "true")
val classNames = List(
"$anonfun$main$1$proxy",
"$anonfun$main$1$proxyImpl_Stub",
"Bar$proxy",
"Bar$proxyImpl_Stub",
"Client$$anonfun$main$1$$anonfun$apply$1$detach",
"Client$proxy",
"Client$proxyImpl_Stub",
"Foo$proxy",
"Foo$proxyImpl_Stub")
val proxyImplNames =
for (n <- classNames; i = n lastIndexOf "_Stub"; if i > 0)
yield n.substring(0, i)
generatePolicyFile()
generateRmiStubs(proxyImplNames)
generateJarFile(classNames)
def generatePolicyFile() {
val in = new BufferedReader(new FileReader(policyTmpl))
val out = new PrintWriter(new BufferedWriter(new FileWriter(policyFile)))
var line = in.readLine()
while (line != null) {
val line1 = line.replaceAll("@PROJECT_LIB_BASE@", codebaseDir)
out.println(line1)
line = in.readLine()
}
in.close()
out.close()
}
def exec(command: String) {
val proc = Runtime.getRuntime exec command
proc.waitFor()
val out = new BufferedReader(new InputStreamReader(proc.getInputStream))
var line = out.readLine()
while (line != null) {
println(line)
line = out.readLine()
}
out.close()
val err = new BufferedReader(new InputStreamReader(proc.getErrorStream))
line = err.readLine()
while (line != null) {
println(line)
line = err.readLine()
}
err.close()
}
def ls(path: String) { exec("ls -al "+path) }
def rmic(options: List[String], classNames: List[String]) {
val javaHome = scala.util.Properties.javaHome
val jdkHome =
if (javaHome endsWith "jre") javaHome.substring(0, javaHome.length-4)
else javaHome
val rmicExt = if (scala.util.Properties.isWin) ".exe" else ""
val rmicCmd = jdkHome+sep+"bin"+sep+"rmic"+rmicExt
val cmdLine = rmicCmd+options.mkString(" ", " ", "")+
classNames.mkString(" "," ","")
// println(cmdLine)
exec(cmdLine)
}
def generateRmiStubs(classNames: List[String]) {
val options = List(
"-v1.2",
"-classpath "+libPath+File.pathSeparator+outPath,
"-d "+outPath)
rmic(options, classNames)
//ls(outPath)
}
def generateJarFile(classNames: List[String]) {
val out = new JarOutputStream(new FileOutputStream(deployJar))
classNames foreach (name => {
val className = name+".class"
out putNextEntry new JarEntry(className)
val in = new FileInputStream(outPath+sep+className)
val buf = new Array[Byte](256)
var len = in read buf
while (len != -1) {
out.write(buf, 0, len)
len = in read buf
}
in.close()
})
out.close()
}
}
}

View File

@ -0,0 +1,25 @@
// See http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html
// See http://mindprod.com/jgloss/policyfile.html
// The policy expands ${/} to the correct path or folder delimiter on your host platform.
// Actions available with SocketPermission: accept, connect, listen, resolve
// 1) The "resolve" action is implied when any of the other actions are present.
// 2) The "listen" action is only meaningful when used with "localhost".
grant {
permission java.net.SocketPermission "*:80", "connect,accept,listen";
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
permission java.util.PropertyPermission "scala.remoting.logLevel", "read";
permission java.util.PropertyPermission "scala.remoting.port", "read";
};
grant codeBase "@PROJECT_LIB_BASE@" {
permission java.lang.RuntimePermission "getClassLoader";
permission java.util.PropertyPermission "java.rmi.server.codebase", "read";
permission java.util.PropertyPermission "java.rmi.server.hostname", "read";
permission java.util.PropertyPermission "sun.rmi.dgc.server.gcInterval", "read,write";
};
//grant {
// permission java.security.AllPermission;
//};

View File

@ -0,0 +1,5 @@
Server.main 8889
> Client.main 127.0.0.1 8889
yInstVal = 10
zLocVal = 1000
result received: 11111

View File

@ -0,0 +1,44 @@
import java.net._, Thread._, ClientHelper._
import scala.remoting._, Debug._
object Foo {
def trace(s: String) { info("[Foo.trace] "+s)}
}
object Client {
val yInstVal: Int = 10
var yInstVar: Int = 99
object Bar {
def trace(s: String) { info("[Bar.trace] "+s) }
}
def main(args: Array[String]) {
init(args)
val server = new Channel(host, port)
val zLocVal: Int = 1000
var zLocVar: Int = 9998
server ! detach(
(x: Int) => {
println("yInstVal = "+yInstVal)
this.trace("yInstVar = "+yInstVar)
Bar.trace("zLocVal = "+zLocVal)
Foo.trace("zLocVar = "+zLocVar)
zLocVar += 2
System.out.println("zLocVal = "+zLocVal)
Debug.info("zLocVar = "+zLocVar)
x + yInstVal + yInstVar + zLocVal + zLocVar
})
val result = server.receiveInt
println("result received: " + result)
}
private def trace(s: String) { info("[Client.trace] "+s) }
}
object ClientHelper {
private var _host = "127.0.0.1"
private var _port = 8888
def host = _host
def port = _port
def init(args: Array[String]) {
try { _host = args(0) } catch { case _ => }
try { _port = args(1).toInt } catch { case _ => }
}
}

View File

@ -0,0 +1,17 @@
import scala.remoting.ServerChannel
object Server extends ServerConsole {
private def computation(f: Int => Int): Int = {
//some time-consuming task
f(2)
}
def main(args: Array[String]) {
val server = new ServerChannel(args(0).toInt)
loop {
val client = server.accept
val f = client.receive[Int => Int]
val result = computation(f)
client ! result
}
server.close()
} }

View File

@ -0,0 +1,80 @@
import java.io._
import scala.compat.Platform.currentTime
import scala.remoting.Debug, Debug._
trait ServerConsole extends Thread {
private val startTime = currentTime
start()
private var isTerminated = false
def terminate() { isTerminated = true }
protected def loop(block: => Unit) {
while (!isTerminated) {
try {
block
}
catch {
case e: ObjectStreamException =>
trace("Object stream error ("+e.getMessage+")")
case e: EOFException =>
trace("Connection lost")
case e: ClassNotFoundException =>
trace("Class not found")
case e =>
trace("Server error: "+e)
}
}
}
override def run() {
import java.io._
val in = new BufferedReader(new InputStreamReader(System.in))
var quit = false
while (!quit) {
val args = getArgs(in)
if (args contains "quit")
quit = true
if (args contains "cls") {
println(ERASE_SCREEN)
println(CURSOR_HOME)
}
if (args contains "warning")
Debug.level = Level.WARNING
if (args contains "info")
Debug.level = Level.INFO
if (args contains "silent")
Debug.level = Level.SILENT
}
terminate()
println("Server exited ("+mkTimeString(currentTime - startTime)+")")
exit(0)
}
protected def trace(msg: String) {
Debug.info("[ServerConsole.trace] "+msg)
}
private def getArgs(in: BufferedReader): List[String] = {
print("> ")
val input = try { in.readLine() } catch { case _ => null }
if (input != null) (input.trim split "\\s+").toList else Nil
}
private def mkTimeString(time: Long): String = {
def twoDigits(i: Long) = (if (i < 10) "0" else "")+i
val sec = time / 1000
val min = sec / 60
val h = min / 60
twoDigits(h) +":"+
twoDigits(min - h * 60)+":"+
twoDigits(sec - min * 60)
}
private val ERASE_SCREEN = "\033[2J"
private val CURSOR_HOME = "\033[H"
}

View File

@ -0,0 +1 @@
-Xpluginsdir ../../../../build/pack/misc/scala-devel/plugins -Xplugin-require:detach -P:detach:enable

View File

@ -0,0 +1,153 @@
object Test {
val host = "127.0.0.1"
val port = 8889
val logLevel = "silent"
// = "info" // debug user code only
// = "info,lib" // debug user & library code
// we assume an Apache server is running locally for deployment
private val sep = java.io.File.separator
val docPath = System.getProperty("user.home")+sep+"public_html"
val docRoot = "http://127.0.0.1/~"+System.getProperty("user.name")
private var server = new ServerThread(port)
private var client = new ClientThread(host, port)
def main(args: Array[String]) {
setenv()
server.start()
Thread.sleep(1000)
client.start()
server.join()
client.join()
System.exit(0)
}
private class ServerThread(port: Int) extends Thread {
override def run() {
println("Server.main "+port)
Server.main(Array(port.toString))
}
}
private class ClientThread(host: String, port: Int) extends Thread {
override def run() {
println("Client.main "+host+" "+port)
Client.main(Array(host, port.toString))
Server.terminate()
}
}
private def setenv() {
import java.io._, java.util.jar._
val policyTmpl =
System.getProperty("partest.cwd")+sep+"basic"+sep+"java.policy"
val outPath = System.getProperty("partest.output")
val libPath = System.getProperty("partest.lib")
val policyFile = outPath+sep+"java.policy"
val codebaseDir = outPath+sep+"-"
assert((new java.io.File(docPath)).isDirectory,
"Root directory \""+docPath+"\" not found")
val deployJar = docPath+sep+"basic_deploy.jar"
val deployUrl = docRoot+"/basic_deploy.jar"
// Java properties for server & client
System.setProperty("scala.remoting.logLevel", logLevel)
System.setProperty("java.security.manager", "")
System.setProperty("java.security.policy", policyFile)
// Java properties for server only
System.setProperty("java.rmi.server.codebase", deployUrl)
System.setProperty("java.rmi.server.hostname", host)
System.setProperty("java.rmi.server.useCodebaseOnly", "true")
val classNames = List(
"Bar$proxy",
"Bar$proxyImpl_Stub",
"Client$$anonfun$main$1$detach",
"Client$proxy",
"Client$proxyImpl_Stub",
"Foo$proxy",
"Foo$proxyImpl_Stub")
val proxyImplNames =
for (n <- classNames; i = n lastIndexOf "_Stub"; if i > 0)
yield n.substring(0, i)
generatePolicyFile()
generateRmiStubs(proxyImplNames)
generateJarFile(classNames)
def generatePolicyFile() {
val in = new BufferedReader(new FileReader(policyTmpl))
val out = new PrintWriter(new BufferedWriter(new FileWriter(policyFile)))
var line = in.readLine()
while (line != null) {
val line1 = line.replaceAll("@PROJECT_LIB_BASE@", codebaseDir)
out.println(line1)
line = in.readLine()
}
in.close()
out.close()
}
def exec(command: String) {
val proc = Runtime.getRuntime exec command
proc.waitFor()
val out = new BufferedReader(new InputStreamReader(proc.getInputStream))
var line = out.readLine()
while (line != null) {
println(line)
line = out.readLine()
}
out.close()
val err = new BufferedReader(new InputStreamReader(proc.getErrorStream))
line = err.readLine()
while (line != null) {
println(line)
line = err.readLine()
}
err.close()
}
def ls(path: String) { exec("ls -al "+path) }
def rmic(options: List[String], classNames: List[String]) {
val javaHome = scala.util.Properties.javaHome
val jdkHome =
if (javaHome endsWith "jre") javaHome.substring(0, javaHome.length-4)
else javaHome
val rmicExt = if (scala.util.Properties.isWin) ".exe" else ""
val rmicCmd = jdkHome+sep+"bin"+sep+"rmic"+rmicExt
val cmdLine = rmicCmd+options.mkString(" ", " ", "")+
classNames.mkString(" "," ","")
// println(cmdLine)
exec(cmdLine)
}
def generateRmiStubs(classNames: List[String]) {
val options = List(
"-v1.2",
"-classpath "+libPath+File.pathSeparator+outPath,
"-d "+outPath)
rmic(options, classNames)
// ls(outPath)
}
def generateJarFile(classNames: List[String]) {
val out = new JarOutputStream(new FileOutputStream(deployJar))
classNames foreach (name => {
val className = name+".class"
out putNextEntry new JarEntry(className)
val in = new FileInputStream(outPath+sep+className)
val buf = new Array[Byte](256)
var len = in read buf
while (len != -1) {
out.write(buf, 0, len)
len = in read buf
}
in.close()
})
out.close()
}
}
}

View File

@ -0,0 +1,26 @@
// See http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html
// See http://mindprod.com/jgloss/policyfile.html
// The policy expands ${/} to the correct path or folder delimiter on your host platform.
// Actions available with SocketPermission: accept, connect, listen, resolve
// 1) The "resolve" action is implied when any of the other actions are present.
// 2) The "listen" action is only meaningful when used with "localhost".
grant {
permission java.net.SocketPermission "*:80", "connect,accept,listen";
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
permission java.util.PropertyPermission "scala.remoting.logLevel", "read";
permission java.util.PropertyPermission "scala.remoting.port", "read";
};
grant codeBase "@PROJECT_LIB_BASE@" {
permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "createClassLoader";
permission java.util.PropertyPermission "java.rmi.server.codebase", "read";
permission java.util.PropertyPermission "java.rmi.server.hostname", "read";
permission java.util.PropertyPermission "sun.rmi.dgc.server.gcInterval", "read,write";
};
//grant {
// permission java.security.AllPermission;
//};