diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-05-23 03:22:01 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-05-23 03:22:01 -0700 |
commit | 0f198a63d2f1a141b43f40f639d5fff8697510d0 (patch) | |
tree | a00c180516a2714ea5107547eae766c82a799f05 /src | |
parent | cebf241ad87358b0e8d2804750a4ac36e76f7091 (diff) | |
parent | 033463f87fe71e8f6d5b17f7cb82b8c2ea5f5271 (diff) | |
download | scala-0f198a63d2f1a141b43f40f639d5fff8697510d0.tar.gz scala-0f198a63d2f1a141b43f40f639d5fff8697510d0.tar.bz2 scala-0f198a63d2f1a141b43f40f639d5fff8697510d0.zip |
Merge pull request #575 from vjovanov/actors-migration-kit
Adding the Actor Migration Kit.
Diffstat (limited to 'src')
22 files changed, 660 insertions, 20 deletions
diff --git a/src/actors-migration/scala/actors/MigrationSystem.scala b/src/actors-migration/scala/actors/MigrationSystem.scala new file mode 100644 index 0000000000..ffc93d9c6f --- /dev/null +++ b/src/actors-migration/scala/actors/MigrationSystem.scala @@ -0,0 +1,36 @@ +package scala.actors + +import scala.collection._ + +object MigrationSystem { + + private[actors] val contextStack = new ThreadLocal[immutable.Stack[Boolean]] { + override def initialValue() = immutable.Stack[Boolean]() + } + + private[this] def withCleanContext(block: => ActorRef): ActorRef = { + // push clean marker + val old = contextStack.get + contextStack.set(old.push(true)) + try { + val instance = block + + if (instance eq null) + throw new Exception("Actor instance passed to actorOf can't be 'null'") + + instance + } finally { + val stackAfter = contextStack.get + if (stackAfter.nonEmpty) + contextStack.set(if (!stackAfter.head) stackAfter.pop.pop else stackAfter.pop) + } + } + + def actorOf(props: Props): ActorRef = withCleanContext { + val creator = props.creator() + val r = new InternalActorRef(creator) + creator.start() + r + } + +}
\ No newline at end of file diff --git a/src/actors-migration/scala/actors/Pattern.scala b/src/actors-migration/scala/actors/Pattern.scala new file mode 100644 index 0000000000..97dbd2cccd --- /dev/null +++ b/src/actors-migration/scala/actors/Pattern.scala @@ -0,0 +1,25 @@ +package scala.actors + +import scala.concurrent.util.Duration + +object pattern { + + implicit def askSupport(ar: ActorRef): AskableActorRef = + new AskableActorRef(ar) +} + +/** + * ActorRef with support for ask(?) operation. + */ +class AskableActorRef(val ar: ActorRef) extends ActorRef { + + def !(message: Any)(implicit sender: ActorRef = null): Unit = ar.!(message)(sender) + + def ?(message: Any)(timeout: Timeout): Future[Any] = ar.?(message, timeout.duration) + + private[actors] def ?(message: Any, timeout: Duration): Future[Any] = ar.?(message, timeout) + + def forward(message: Any) = ar.forward(message) + + private[actors] def localActor: AbstractActor = ar.localActor +}
\ No newline at end of file diff --git a/src/actors-migration/scala/actors/Props.scala b/src/actors-migration/scala/actors/Props.scala new file mode 100644 index 0000000000..891e23213a --- /dev/null +++ b/src/actors-migration/scala/actors/Props.scala @@ -0,0 +1,13 @@ +package scala.actors + +/** + * ActorRef configuration object. It represents the minimal subset of Akka Props class. + */ +case class Props(creator: () ⇒ InternalActor, dispatcher: String) { + + /** + * Returns a new Props with the specified creator set + */ + def withCreator(c: ⇒ InternalActor) = copy(creator = () ⇒ c) + +} diff --git a/src/actors-migration/scala/actors/StashingActor.scala b/src/actors-migration/scala/actors/StashingActor.scala new file mode 100644 index 0000000000..37300f9d63 --- /dev/null +++ b/src/actors-migration/scala/actors/StashingActor.scala @@ -0,0 +1,255 @@ +package scala.actors + +import scala.collection._ +import scala.concurrent.util.Duration +import java.util.concurrent.TimeUnit + +object StashingActor extends Combinators { + implicit def mkBody[A](body: => A) = new InternalActor.Body[A] { + def andThen[B](other: => B): Unit = Actor.rawSelf.seq(body, other) + } +} + +@deprecated("Scala Actors are being removed from the standard library. Please refer to the migration guide.", "2.10") +trait StashingActor extends InternalActor { + type Receive = PartialFunction[Any, Unit] + + // checks if StashingActor is created within the actorOf block + creationCheck; + + private[actors] val ref = new InternalActorRef(this) + + val self: ActorRef = ref + + protected[this] val context: ActorContext = new ActorContext(this) + + @volatile + private var myTimeout: Option[Long] = None + + private val stash = new MQueue[Any]("Stash") + + /** + * Migration notes: + * this method replaces receiveWithin, receive and react methods from Scala Actors. + */ + def receive: Receive + + /** + * User overridable callback. + * <p/> + * Is called when an Actor is started by invoking 'actor'. + */ + def preStart() {} + + /** + * User overridable callback. + * <p/> + * Is called when 'actor.stop()' is invoked. + */ + def postStop() {} + + /** + * User overridable callback. + * <p/> + * Is called on a crashed Actor right BEFORE it is restarted to allow clean + * up of resources before Actor is terminated. + * By default it calls postStop() + */ + def preRestart(reason: Throwable, message: Option[Any]) { postStop() } + + /** + * Changes the Actor's behavior to become the new 'Receive' (PartialFunction[Any, Unit]) handler. + * Puts the behavior on top of the hotswap stack. + * If "discardOld" is true, an unbecome will be issued prior to pushing the new behavior to the stack + */ + private def become(behavior: Receive, discardOld: Boolean = true) { + if (discardOld) unbecome() + behaviorStack = behaviorStack.push(wrapWithSystemMessageHandling(behavior)) + } + + /** + * Reverts the Actor behavior to the previous one in the hotswap stack. + */ + private def unbecome() { + // never unbecome the initial behavior + if (behaviorStack.size > 1) + behaviorStack = behaviorStack.pop + } + + /** + * User overridable callback. + * <p/> + * Is called when a message isn't handled by the current behavior of the actor + * by default it does: EventHandler.warning(self, message) + */ + def unhandled(message: Any) { + message match { + case Terminated(dead) ⇒ throw new DeathPactException(dead) + case _ ⇒ System.err.println("Unhandeled message " + message) + } + } + + protected def sender: ActorRef = new OutputChannelRef(internalSender) + + override def act(): Unit = internalAct() + + override def start(): StashingActor = { + super.start() + this + } + + override def receive[R](f: PartialFunction[Any, R]): R + + /* + * Internal implementation. + */ + + private[actors] var behaviorStack = immutable.Stack[PartialFunction[Any, Unit]]() + + /* + * Checks that StashingActor can be created only by MigrationSystem.actorOf method. + */ + private[this] def creationCheck = { + + // creation check (see ActorRef) + val context = MigrationSystem.contextStack.get + if (context.isEmpty) + throw new RuntimeException("In order to create StashingActor one must use actorOf.") + else { + if (!context.head) + throw new RuntimeException("Only one actor can be created per actorOf call.") + else + MigrationSystem.contextStack.set(context.push(false)) + } + + } + + private[actors] override def preAct() { + preStart() + } + + /** + * Adds message to a stash, to be processed later. Stashed messages can be fed back into the $actor's + * mailbox using <code>unstashAll()</code>. + * + * Temporarily stashing away messages that the $actor does not (yet) handle simplifies implementing + * certain messaging protocols. + */ + final def stash(msg: Any): Unit = { + stash.append(msg, null) + } + + final def unstashAll(): Unit = { + mailbox.prepend(stash) + stash.clear() + } + + /** + * Wraps any partial function with Exit message handling. + */ + private[actors] def wrapWithSystemMessageHandling(pf: PartialFunction[Any, Unit]): PartialFunction[Any, Unit] = { + + def swapExitHandler(pf: PartialFunction[Any, Unit]) = new PartialFunction[Any, Unit] { + def swapExit(v: Any) = v match { + case Exit(from, reason) => + Terminated(new InternalActorRef(from.asInstanceOf[InternalActor])) + case v => v + } + + def isDefinedAt(v: Any) = pf.isDefinedAt(swapExit(v)) + def apply(v: Any) = pf(swapExit(v)) + } + + swapExitHandler(pf orElse { + case m => unhandled(m) + }) + } + + /** + * Method that models the behavior of Akka actors. + */ + private[actors] def internalAct() { + trapExit = true + behaviorStack = behaviorStack.push(wrapWithSystemMessageHandling(receive)) + loop { + if (myTimeout.isDefined) + reactWithin(myTimeout.get)(behaviorStack.top) + else + react(behaviorStack.top) + } + } + + private[actors] override def internalPostStop() = postStop() + + // Used for pattern matching statement similar to Akka + lazy val ReceiveTimeout = TIMEOUT + + /** + * Used to simulate Akka context behavior. Should be used only for migration purposes. + */ + protected[actors] class ActorContext(val actr: StashingActor) { + + /** + * Changes the Actor's behavior to become the new 'Receive' (PartialFunction[Any, Unit]) handler. + * Puts the behavior on top of the hotswap stack. + * If "discardOld" is true, an unbecome will be issued prior to pushing the new behavior to the stack + */ + def become(behavior: Receive, discardOld: Boolean = true) = actr.become(behavior, discardOld) + + /** + * Reverts the Actor behavior to the previous one in the hotswap stack. + */ + def unbecome() = actr.unbecome() + + /** + * Shuts down the actor its dispatcher and message queue. + */ + def stop(subject: ActorRef): Nothing = if (subject != ref) + throw new RuntimeException("Only stoping of self is allowed during migration.") + else + actr.exit() + + /** + * Registers this actor as a Monitor for the provided ActorRef. + * @return the provided ActorRef + */ + def watch(subject: ActorRef): ActorRef = { + actr.watch(subject) + subject + } + + /** + * Unregisters this actor as Monitor for the provided ActorRef. + * @return the provided ActorRef + */ + def unwatch(subject: ActorRef): ActorRef = { + actr unwatch subject + subject + } + + /** + * Defines the receiver timeout value. + */ + final def setReceiveTimeout(timeout: Duration): Unit = + actr.myTimeout = Some(timeout.toMillis) + + /** + * Gets the current receiveTimeout + */ + final def receiveTimeout: Option[Duration] = + actr.myTimeout.map(Duration(_, TimeUnit.MILLISECONDS)) + + } +} + +/** + * This message is thrown by default when an Actor does not handle termination. + */ +class DeathPactException(ref: ActorRef = null) extends Exception { + override def fillInStackTrace() = this //Don't waste cycles generating stack trace +} + +/** + * Message that is sent to a watching actor when the watched actor terminates. + */ +case class Terminated(actor: ActorRef) diff --git a/src/actors-migration/scala/actors/Timeout.scala b/src/actors-migration/scala/actors/Timeout.scala new file mode 100644 index 0000000000..0d9532a14b --- /dev/null +++ b/src/actors-migration/scala/actors/Timeout.scala @@ -0,0 +1,39 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2005-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.actors + +import scala.concurrent.util.Duration +import java.util.concurrent.TimeUnit + +case class Timeout(duration: Duration) { + def this(timeout: Long) = this(Duration(timeout, TimeUnit.MILLISECONDS)) + def this(length: Long, unit: TimeUnit) = this(Duration(length, unit)) +} + +object Timeout { + + /** + * A timeout with zero duration, will cause most requests to always timeout. + */ + val zero = new Timeout(Duration.Zero) + + /** + * A Timeout with infinite duration. Will never timeout. Use extreme caution with this + * as it may cause memory leaks, blocked threads, or may not even be supported by + * the receiver, which would result in an exception. + */ + val never = new Timeout(Duration.Inf) + + def apply(timeout: Long) = new Timeout(timeout) + def apply(length: Long, unit: TimeUnit) = new Timeout(length, unit) + + implicit def durationToTimeout(duration: Duration) = new Timeout(duration) + implicit def intToTimeout(timeout: Int) = new Timeout(timeout) + implicit def longToTimeout(timeout: Long) = new Timeout(timeout) +} diff --git a/src/actors/scala/actors/ActorRef.scala b/src/actors/scala/actors/ActorRef.scala new file mode 100644 index 0000000000..8f70b13e01 --- /dev/null +++ b/src/actors/scala/actors/ActorRef.scala @@ -0,0 +1,119 @@ +package scala.actors + +import java.util.concurrent.TimeoutException +import scala.concurrent.util.Duration + +/** + * Trait used for migration of Scala actors to Akka. + */ +@deprecated("ActorRef ought to be used only with the Actor Migration Kit.") +trait ActorRef { + + /** + * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. + * <p/> + * + * If invoked from within an actor then the actor reference is implicitly passed on as the implicit 'sender' argument. + * <p/> + * + * This actor 'sender' reference is then available in the receiving actor in the 'sender' member variable, + * if invoked from within an Actor. If not then no sender is available. + * <pre> + * actor ! message + * </pre> + * <p/> + */ + def !(message: Any)(implicit sender: ActorRef = null): Unit + + /** + * Sends a message asynchronously, returning a future which may eventually hold the reply. + */ + private[actors] def ?(message: Any, timeout: Duration): Future[Any] + + /** + * Forwards the message and passes the original sender actor as the sender. + * <p/> + * Works with '!' and '?'. + */ + def forward(message: Any) + + private[actors] def localActor: AbstractActor + +} + +private[actors] class OutputChannelRef(val actor: OutputChannel[Any]) extends ActorRef { + + override private[actors] def ?(message: Any, timeout: Duration): Future[Any] = + throw new UnsupportedOperationException("Output channel does not support ?") + + /** + * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. + * <p/> + * + * <p/> + * <pre> + * actor ! message + * </pre> + * <p/> + */ + def !(message: Any)(implicit sender: ActorRef = null): Unit = + if (sender != null) + actor.send(message, sender.localActor) + else + actor ! message + + override def equals(that: Any) = + that.isInstanceOf[OutputChannelRef] && that.asInstanceOf[OutputChannelRef].actor == this.actor + + private[actors] override def localActor: AbstractActor = + throw new UnsupportedOperationException("Output channel does not have an instance of the actor") + + def forward(message: Any): Unit = throw new UnsupportedOperationException("OutputChannel does not support forward.") + +} + +private[actors] class ReactorRef(override val actor: Reactor[Any]) extends OutputChannelRef(actor) { + + /** + * Forwards the message and passes the original sender actor as the sender. + * <p/> + * Works with '!' and '?'. + */ + override def forward(message: Any) = actor.forward(message) + +} + +private[actors] final class InternalActorRef(override val actor: InternalActor) extends ReactorRef(actor) { + + /** + * Sends a message asynchronously, returning a future which may eventually hold the reply. + */ + override private[actors] def ?(message: Any, timeout: Duration): Future[Any] = + Futures.future { + val dur = if (timeout.isFinite()) timeout.toMillis else (java.lang.Long.MAX_VALUE >> 2) + actor !? (dur, message) match { + case Some(x) => x + case None => new AskTimeoutException("? operation timed out.") + } + } + + override def !(message: Any)(implicit sender: ActorRef = null): Unit = + if (message == PoisonPill) + actor.stop('normal) + else if (sender != null) + actor.send(message, sender.localActor) + else + actor ! message + + private[actors] override def localActor: InternalActor = this.actor +} + +/** + * This is what is used to complete a Future that is returned from an ask/? call, + * when it times out. + */ +class AskTimeoutException(message: String, cause: Throwable) extends TimeoutException { + def this(message: String) = this(message, null: Throwable) +} + +object PoisonPill diff --git a/src/actors/scala/actors/ActorTask.scala b/src/actors/scala/actors/ActorTask.scala index bb04302238..045b00f5f2 100644 --- a/src/actors/scala/actors/ActorTask.scala +++ b/src/actors/scala/actors/ActorTask.scala @@ -51,7 +51,6 @@ private[actors] class ActorTask(actor: InternalActor, super.terminateExecution(e) () => {} } - actor.internalPostStop res } diff --git a/src/actors/scala/actors/InternalActor.scala b/src/actors/scala/actors/InternalActor.scala index c94da5b9fd..cb66021d1c 100644 --- a/src/actors/scala/actors/InternalActor.scala +++ b/src/actors/scala/actors/InternalActor.scala @@ -153,7 +153,7 @@ private[actors] trait InternalActor extends AbstractActor with InternalReplyReac val matches = f.isDefinedAt(m) senders = senders.tail matches - }) + }) if (null eq qel) { val todo = synchronized { // in mean time new stuff might have arrived @@ -317,6 +317,35 @@ private[actors] trait InternalActor extends AbstractActor with InternalReplyReac } /** + * Links <code>self</code> to actor <code>to</code>. + * + * @param to the actor to link to + * @return the parameter actor + */ + def link(to: ActorRef): ActorRef = { + this.link(to.localActor) + to + } + + /** + * Unidirectional linking. For migration purposes only + */ + private[actors] def watch(subject: ActorRef): ActorRef = { + assert(Actor.self(scheduler) == this, "link called on actor different from self") + subject.localActor linkTo this + subject + } + + /** + * Unidirectional linking. For migration purposes only + */ + private[actors] def unwatch(subject: ActorRef): ActorRef = { + assert(Actor.self(scheduler) == this, "link called on actor different from self") + subject.localActor unlinkFrom this + subject + } + + /** * Links <code>self</code> to the actor defined by <code>body</code>. * * @param body the body of the actor to link to @@ -346,17 +375,24 @@ private[actors] trait InternalActor extends AbstractActor with InternalReplyReac from unlinkFrom this } + /** + * Unlinks <code>self</code> from actor <code>from</code>. + */ + def unlink(from: ActorRef) { + unlink(from.localActor) + } + private[actors] def unlinkFrom(from: AbstractActor) = synchronized { links = links.filterNot(from.==) } - @volatile + @volatile private[actors] var _trapExit = false - + def trapExit = _trapExit - + def trapExit_=(value: Boolean) = _trapExit = value - + // guarded by this private var exitReason: AnyRef = 'normal // guarded by this @@ -445,12 +481,11 @@ private[actors] trait InternalActor extends AbstractActor with InternalReplyReac scheduler.onTerminate(this) { f } } - private[actors] def internalPostStop() = {} - private[actors] def stop(reason: AnyRef): Unit = { + private[actors] def stop(reason: AnyRef): Unit = { synchronized { shouldExit = true - exitReason = reason + exitReason = reason // resume this Actor in a way that // causes it to exit // (because shouldExit == true) @@ -464,7 +499,7 @@ private[actors] trait InternalActor extends AbstractActor with InternalReplyReac /* Here we should not throw a SuspendActorControl, since the current method is called from an actor that is in the process of exiting. - + Therefore, the contract for scheduleActor is that it never throws a SuspendActorControl. */ diff --git a/src/actors/scala/actors/MQueue.scala b/src/actors/scala/actors/MQueue.scala index 65427d68c5..4a148d2cb3 100644 --- a/src/actors/scala/actors/MQueue.scala +++ b/src/actors/scala/actors/MQueue.scala @@ -25,6 +25,20 @@ private[actors] class MQueue[Msg >: Null](protected val label: String) { _size += diff } + def prepend(other: MQueue[Msg]) { + if (!other.isEmpty) { + other.last.next = first + first = other.first + } + } + + def clear() { + first = null + last = null + _size = 0 + } + + def append(msg: Msg, session: OutputChannel[Any]) { changeSize(1) // size always increases by 1 val el = new MQueueElement(msg, session) diff --git a/src/actors/scala/actors/Reactor.scala b/src/actors/scala/actors/Reactor.scala index 206a97d97c..7a8d738758 100644 --- a/src/actors/scala/actors/Reactor.scala +++ b/src/actors/scala/actors/Reactor.scala @@ -214,11 +214,16 @@ trait Reactor[Msg >: Null] extends OutputChannel[Msg] with Combinators { scheduler executeFromActor makeReaction(null, handler, msg) } + private[actors] def preAct() = {} + // guarded by this private[actors] def dostart() { _state = Actor.State.Runnable scheduler newActor this - scheduler execute makeReaction(() => act(), null, null) + scheduler execute makeReaction(() => { + preAct() + act() + }, null, null) } /** @@ -285,12 +290,15 @@ trait Reactor[Msg >: Null] extends OutputChannel[Msg] with Combinators { throw Actor.suspendException } + private[actors] def internalPostStop() = {} + private[actors] def terminated() { synchronized { _state = Actor.State.Terminated // reset waitingFor, otherwise getState returns Suspended waitingFor = Reactor.waitingForNone } + internalPostStop() scheduler.terminated(this) } diff --git a/src/actors/scala/actors/ReplyReactor.scala b/src/actors/scala/actors/ReplyReactor.scala index 0ffbbd3cce..83d7ba0f7f 100644 --- a/src/actors/scala/actors/ReplyReactor.scala +++ b/src/actors/scala/actors/ReplyReactor.scala @@ -7,10 +7,7 @@ \* */ package scala.actors -@deprecated("Scala Actors are beeing removed from the standard library. Please refer to the migration guide.", "2.10") +@deprecated("Scala Actors are being removed from the standard library. Please refer to the migration guide.", "2.10") trait ReplyReactor extends InternalReplyReactor { - - protected[actors] def sender: OutputChannel[Any] = super.internalSender - + protected[actors] def sender: OutputChannel[Any] = super.internalSender } - diff --git a/src/build/maven/maven-deploy.xml b/src/build/maven/maven-deploy.xml index ac0f8f745b..7ab54f81c3 100644 --- a/src/build/maven/maven-deploy.xml +++ b/src/build/maven/maven-deploy.xml @@ -112,6 +112,7 @@ <deploy-local name="scala-compiler" version="@{version}" repository="@{repository}" /> <deploy-local-plugin name="continuations" version="@{version}" repository="@{repository}"/> <deploy-local name="scala-actors" version="@{version}" repository="@{repository}" /> + <deploy-local name="scala-actors-migration" version="@{version}" repository="@{repository}" /> <deploy-local name="scala-swing" version="@{version}" repository="@{repository}"/> <deploy-local name="scalap" version="@{version}" repository="@{repository}"/> <deploy-local name="scala-partest" version="@{version}" repository="@{repository}"/> @@ -172,6 +173,7 @@ <deploy-remote name="scala-compiler" version="@{version}" repository="@{repository}" /> <deploy-remote name="scala-swing" version="@{version}" repository="@{repository}"/> <deploy-remote name="scala-actors" version="@{version}" repository="@{repository}"/> + <deploy-remote name="scala-actors-migration" version="@{version}" repository="@{repository}"/> <deploy-remote name="scalap" version="@{version}" repository="@{repository}"/> <deploy-remote name="scala-partest" version="@{version}" repository="@{repository}"/> <deploy-remote-plugin name="continuations" version="@{version}" repository="@{repository}"/> @@ -239,6 +241,7 @@ <deploy-remote-signed name="scala-compiler" version="@{version}" repository="@{repository}" /> <deploy-remote-signed name="scala-swing" version="@{version}" repository="@{repository}"/> <deploy-remote-signed name="scala-actors" version="@{version}" repository="@{repository}"/> + <deploy-remote-signed name="scala-actors-migration" version="@{version}" repository="@{repository}"/> <deploy-remote-signed name="scalap" version="@{version}" repository="@{repository}"/> <deploy-remote-signed name="scala-partest" version="@{version}" repository="@{repository}"/> </sequential> diff --git a/src/build/maven/scala-actors-migration.pom b/src/build/maven/scala-actors-migration.pom new file mode 100644 index 0000000000..93fc34ece9 --- /dev/null +++ b/src/build/maven/scala-actors-migration.pom @@ -0,0 +1,66 @@ +<project + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.scala-lang</groupId> + <artifactId>scala-actors-migration</artifactId> + <packaging>jar</packaging> + <version>@VERSION@</version> + <name>Scala Migration Kit</name> + <description>Migration kit that enables easy transition from the Scala Actors to Akka.</description> + <url>http://www.scala-lang.org/</url> + <inceptionYear>2012</inceptionYear> + <organization> + <name>LAMP/EPFL</name> + <url>http://lamp.epfl.ch/</url> + </organization> + <licenses> + <license> + <name>BSD-like</name> + <url>http://www.scala-lang.org/downloads/license.html + </url> + <distribution>repo</distribution> + </license> + </licenses> + <scm> + <connection>scm:git:git://github.com/scala/scala.git</connection> + <url>https://github.com/scala/scala.git</url> + </scm> + <issueManagement> + <system>JIRA</system> + <url>https://issues.scala-lang.org/</url> + </issueManagement> + <dependencies> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <version>@VERSION@</version> + </dependency> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-actors</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + <distributionManagement> + <repository> + <id>scala-tools.org</id> + <url>@RELEASE_REPOSITORY@</url> + </repository> + <snapshotRepository> + <id>scala-tools.org</id> + <url>@SNAPSHOT_REPOSITORY@</url> + <uniqueVersion>false</uniqueVersion> + </snapshotRepository> + </distributionManagement> + <developers> + <developer> + <id>lamp</id> + <name>EPFL LAMP</name> + </developer> + <developer> + <id>Typesafe</id> + <name>Typesafe, Inc.</name> + </developer> + </developers> +</project> diff --git a/src/build/pack.xml b/src/build/pack.xml index f96c6b9799..956beaef88 100644 --- a/src/build/pack.xml +++ b/src/build/pack.xml @@ -139,6 +139,7 @@ MAIN DISTRIBUTION PACKAGING <mvn-copy-lib mvn.artifact.name="scala-compiler"/> <mvn-copy-lib mvn.artifact.name="scala-swing"/> <mvn-copy-lib mvn.artifact.name="scala-actors"/> + <mvn-copy-lib mvn.artifact.name="scala-actors-migration"/> <mvn-copy-lib mvn.artifact.name="scala-partest"/> <mvn-copy-lib mvn.artifact.name="scalap"/> </target> @@ -201,6 +202,11 @@ MAIN DISTRIBUTION PACKAGING basedir="${build-docs.dir}/continuations-plugin"> <include name="**/*"/> </jar> + <jar destfile="${dists.dir}/maven/${version.number}/scala-actors-migration/scala-actors-migration-docs.jar" + basedir="${build-docs.dir}/actors-migration"> + <include name="**/*"/> + </jar> + <!-- TODO - Scala swing and actors should maybe have thier own jar, but creating it is SLOW. --> <copy tofile="${dists.dir}/maven/${version.number}/scala-swing/scala-swing-docs.jar" file="${dists.dir}/maven/${version.number}/scala-library/scala-library-docs.jar"/> diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala index ad2e155182..67b38d2e24 100644 --- a/src/partest/scala/tools/partest/PartestTask.scala +++ b/src/partest/scala/tools/partest/PartestTask.scala @@ -309,6 +309,16 @@ class PartestTask extends Task with CompilationPathProperty { } } getOrElse sys.error("Provided classpath does not contain a Scala actors.") + val scalaActorsMigration = { + (classpath.list map { fs => new File(fs) }) find { f => + f.getName match { + case "scala-actors-migration.jar" => true + case "actors-migration" if (f.getParentFile.getName == "classes") => true + case _ => false + } + } + } getOrElse sys.error("Provided classpath does not contain a Scala actors.") + def scalacArgsFlat: Option[Seq[String]] = scalacArgs map (_ flatMap { a => val parts = a.getParts if(parts eq null) Seq[String]() else parts.toSeq @@ -335,6 +345,7 @@ class PartestTask extends Task with CompilationPathProperty { antFileManager.LATEST_COMP = scalaCompiler.getAbsolutePath antFileManager.LATEST_PARTEST = scalaPartest.getAbsolutePath antFileManager.LATEST_ACTORS = scalaActors.getAbsolutePath + antFileManager.LATEST_ACTORS_MIGRATION = scalaActorsMigration.getAbsolutePath javacmd foreach (x => antFileManager.JAVACMD = x.getAbsolutePath) javaccmd foreach (x => antFileManager.JAVAC_CMD = x.getAbsolutePath) diff --git a/src/partest/scala/tools/partest/nest/AntRunner.scala b/src/partest/scala/tools/partest/nest/AntRunner.scala index e77385d6e9..dc83e4ea66 100644 --- a/src/partest/scala/tools/partest/nest/AntRunner.scala +++ b/src/partest/scala/tools/partest/nest/AntRunner.scala @@ -23,6 +23,7 @@ class AntRunner extends DirectRunner { var LATEST_COMP: String = _ var LATEST_PARTEST: String = _ var LATEST_ACTORS: String = _ + var LATEST_ACTORS_MIGRATION: String = _ val testRootPath: String = "test" val testRootDir: Directory = Directory(testRootPath) } diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala index 8d239a84bd..b270a6b65a 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala @@ -84,6 +84,7 @@ class ConsoleFileManager extends FileManager { latestFile = testClassesDir.parent / "bin" latestLibFile = testClassesDir / "library" latestActorsFile = testClassesDir / "library" / "actors" + latestActMigFile = testClassesDir / "actors-migration" latestCompFile = testClassesDir / "compiler" latestPartestFile = testClassesDir / "partest" latestFjbgFile = testParent / "lib" / "fjbg.jar" @@ -94,6 +95,7 @@ class ConsoleFileManager extends FileManager { latestFile = dir / "bin" latestLibFile = dir / "lib/scala-library.jar" latestActorsFile = dir / "lib/scala-actors.jar" + latestActMigFile = dir / "lib/scala-actors-migration.jar" latestCompFile = dir / "lib/scala-compiler.jar" latestPartestFile = dir / "lib/scala-partest.jar" latestFjbgFile = testParent / "lib" / "fjbg.jar" @@ -104,6 +106,7 @@ class ConsoleFileManager extends FileManager { latestFile = prefixFile("build/quick/bin") latestLibFile = prefixFile("build/quick/classes/library") latestActorsFile = prefixFile("build/quick/classes/library/actors") + latestActMigFile = prefixFile("build/quick/classes/actors-migration") latestCompFile = prefixFile("build/quick/classes/compiler") latestPartestFile = prefixFile("build/quick/classes/partest") } @@ -114,6 +117,7 @@ class ConsoleFileManager extends FileManager { latestFile = prefixFileWith(p, "bin") latestLibFile = prefixFileWith(p, "lib/scala-library.jar") latestActorsFile = prefixFileWith(p, "lib/scala-actors.jar") + latestActMigFile = prefixFileWith(p, "lib/scala-actors-migration.jar") latestCompFile = prefixFileWith(p, "lib/scala-compiler.jar") latestPartestFile = prefixFileWith(p, "lib/scala-partest.jar") } @@ -123,6 +127,7 @@ class ConsoleFileManager extends FileManager { latestFile = prefixFile("dists/latest/bin") latestLibFile = prefixFile("dists/latest/lib/scala-library.jar") latestActorsFile = prefixFile("dists/latest/lib/scala-actors.jar") + latestActMigFile = prefixFile("dists/latest/lib/scala-actors-migration.jar") latestCompFile = prefixFile("dists/latest/lib/scala-compiler.jar") latestPartestFile = prefixFile("dists/latest/lib/scala-partest.jar") } @@ -132,6 +137,7 @@ class ConsoleFileManager extends FileManager { latestFile = prefixFile("build/pack/bin") latestLibFile = prefixFile("build/pack/lib/scala-library.jar") latestActorsFile = prefixFile("build/pack/lib/scala-actors.jar") + latestActMigFile = prefixFile("build/pack/lib/scala-actors-migration.jar") latestCompFile = prefixFile("build/pack/lib/scala-compiler.jar") latestPartestFile = prefixFile("build/pack/lib/scala-partest.jar") } @@ -167,16 +173,19 @@ class ConsoleFileManager extends FileManager { LATEST_COMP = latestCompFile.getAbsolutePath LATEST_PARTEST = latestPartestFile.getAbsolutePath LATEST_ACTORS = latestActorsFile.getAbsolutePath + LATEST_ACTORS_MIGRATION = latestActMigFile.getAbsolutePath } var LATEST_LIB: String = "" var LATEST_COMP: String = "" var LATEST_PARTEST: String = "" var LATEST_ACTORS: String = "" + var LATEST_ACTORS_MIGRATION: String = "" var latestFile: File = _ var latestLibFile: File = _ var latestActorsFile: File = _ + var latestActMigFile: File = _ var latestCompFile: File = _ var latestPartestFile: File = _ var latestFjbgFile: File = _ diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala index 20f435cfbb..815c27f567 100644 --- a/src/partest/scala/tools/partest/nest/DirectRunner.scala +++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala @@ -61,10 +61,10 @@ trait DirectRunner { val latestLibFile = new File(fileManager.LATEST_LIB) val latestPartestFile = new File(fileManager.LATEST_PARTEST) val latestActorsFile = new File(fileManager.LATEST_ACTORS) - + val latestActMigFile = new File(fileManager.LATEST_ACTORS_MIGRATION) val scalacheckURL = PathSettings.scalaCheck.toURL val scalaCheckParentClassLoader = ScalaClassLoader.fromURLs( - scalacheckURL :: (List(latestCompFile, latestLibFile, latestActorsFile, latestPartestFile).map(_.toURI.toURL)) + scalacheckURL :: (List(latestCompFile, latestLibFile, latestActorsFile, latestActMigFile, latestPartestFile).map(_.toURI.toURL)) ) Output.init() diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala index 6d9e64730f..cf7160f521 100644 --- a/src/partest/scala/tools/partest/nest/FileManager.scala +++ b/src/partest/scala/tools/partest/nest/FileManager.scala @@ -63,6 +63,7 @@ trait FileManager extends FileUtil { var LATEST_COMP: String var LATEST_PARTEST: String var LATEST_ACTORS: String + var LATEST_ACTORS_MIGRATION: String var showDiff = false var updateCheck = false diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala index a0511774a9..a5d5952ff7 100644 --- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -48,9 +48,9 @@ class ReflectiveRunner { new ConsoleFileManager import fileManager. - { latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile } + { latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile, latestActMigFile } val files = - Array(latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile) map (x => io.File(x)) + Array(latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile, latestActMigFile) map (x => io.File(x)) val sepUrls = files map (_.toURL) var sepLoader = new URLClassLoader(sepUrls, null) diff --git a/src/partest/scala/tools/partest/nest/SBTRunner.scala b/src/partest/scala/tools/partest/nest/SBTRunner.scala index 5d994eeb37..14e2dc3df9 100644 --- a/src/partest/scala/tools/partest/nest/SBTRunner.scala +++ b/src/partest/scala/tools/partest/nest/SBTRunner.scala @@ -16,6 +16,7 @@ object SBTRunner extends DirectRunner { var LATEST_COMP: String = _ var LATEST_PARTEST: String = _ var LATEST_ACTORS: String = _ + var LATEST_ACTORS_MIGRATION: String = _ val testRootPath: String = "test" val testRootDir: Directory = Directory(testRootPath) } @@ -65,6 +66,7 @@ object SBTRunner extends DirectRunner { fileManager.LATEST_COMP = findClasspath("scala-compiler", "scala-compiler") getOrElse sys.error("No scala-compiler found! Classpath = " + fileManager.CLASSPATH) fileManager.LATEST_PARTEST = findClasspath("scala-partest", "partest") getOrElse sys.error("No scala-partest found! Classpath = " + fileManager.CLASSPATH) fileManager.LATEST_ACTORS = findClasspath("scala-actors", "actors") getOrElse sys.error("No scala-actors found! Classpath = " + fileManager.CLASSPATH) + fileManager.LATEST_ACTORS_MIGRATION = findClasspath("scala-actors-migration", "actors-migration") getOrElse sys.error("No scala-actors-migration found! Classpath = " + fileManager.CLASSPATH) // TODO - Do something useful here!!! fileManager.JAVAC_CMD = "javac" diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala index 9326a8b232..40325c6375 100644 --- a/src/partest/scala/tools/partest/nest/Worker.scala +++ b/src/partest/scala/tools/partest/nest/Worker.scala @@ -56,6 +56,7 @@ class ScalaCheckFileManager(val origmanager: FileManager) extends FileManager { var LATEST_COMP: String = origmanager.LATEST_COMP var LATEST_PARTEST: String = origmanager.LATEST_PARTEST var LATEST_ACTORS: String = origmanager.LATEST_ACTORS + var LATEST_ACTORS_MIGRATION: String = origmanager.LATEST_ACTORS_MIGRATION } object Output { |