add and verify Java API for actorFor/ActorPath, fixes #1343
This commit is contained in:
parent
56dc18106b
commit
a0a44abe0d
6 changed files with 80 additions and 31 deletions
|
|
@ -51,7 +51,11 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
system.actorFor(system / "c1") must be === c1
|
system.actorFor(system / "c1") must be === c1
|
||||||
system.actorFor(system / "c2") must be === c2
|
system.actorFor(system / "c2") must be === c2
|
||||||
system.actorFor(system / "c2" / "c21") must be === c21
|
system.actorFor(system / "c2" / "c21") must be === c21
|
||||||
|
system.actorFor(system child "c2" child "c21") must be === c21 // test Java API
|
||||||
system.actorFor(system / Seq("c2", "c21")) must be === c21
|
system.actorFor(system / Seq("c2", "c21")) must be === c21
|
||||||
|
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
system.actorFor(system descendant Seq("c2", "c21").asJava) // test Java API
|
||||||
}
|
}
|
||||||
|
|
||||||
"find actors by looking up their string representation" in {
|
"find actors by looking up their string representation" in {
|
||||||
|
|
@ -75,7 +79,7 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
"find actors by looking up their path elements" in {
|
"find actors by looking up their path elements" in {
|
||||||
system.actorFor(c1.path.elements) must be === c1
|
system.actorFor(c1.path.elements) must be === c1
|
||||||
system.actorFor(c2.path.elements) must be === c2
|
system.actorFor(c2.path.elements) must be === c2
|
||||||
system.actorFor(c21.path.elements) must be === c21
|
system.actorFor(c21.path.getElements) must be === c21 // test Java API
|
||||||
}
|
}
|
||||||
|
|
||||||
"find system-generated actors" in {
|
"find system-generated actors" in {
|
||||||
|
|
@ -190,6 +194,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
}
|
}
|
||||||
|
|
||||||
"return deadLetters for non-existing paths" in {
|
"return deadLetters for non-existing paths" in {
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
|
||||||
def checkOne(looker: ActorRef, query: Query) {
|
def checkOne(looker: ActorRef, query: Query) {
|
||||||
(looker ? query).get must be === system.deadLetters
|
(looker ? query).get must be === system.deadLetters
|
||||||
}
|
}
|
||||||
|
|
@ -198,6 +204,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
LookupString(""),
|
LookupString(""),
|
||||||
LookupString("akka://all-systems/Nobody"),
|
LookupString("akka://all-systems/Nobody"),
|
||||||
LookupPath(system / "hallo"),
|
LookupPath(system / "hallo"),
|
||||||
|
LookupPath(looker.path child "hallo"), // test Java API
|
||||||
|
LookupPath(looker.path descendant Seq("a", "b").asJava), // test Java API
|
||||||
LookupElems(Seq()),
|
LookupElems(Seq()),
|
||||||
LookupElems(Seq("a"))) foreach (checkOne(looker, _))
|
LookupElems(Seq("a"))) foreach (checkOne(looker, _))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,16 +49,37 @@ sealed trait ActorPath extends Comparable[ActorPath] {
|
||||||
*/
|
*/
|
||||||
def /(child: String): ActorPath
|
def /(child: String): ActorPath
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ''Java API'': Create a new child actor path.
|
||||||
|
*/
|
||||||
|
def child(child: String): ActorPath = /(child)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively create a descendant’s path by appending all child names.
|
* Recursively create a descendant’s path by appending all child names.
|
||||||
*/
|
*/
|
||||||
def /(child: Iterable[String]): ActorPath = (this /: child)(_ / _)
|
def /(child: Iterable[String]): ActorPath = (this /: child)(_ / _)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sequence of names for this path. Performance implication: has to allocate a list.
|
* ''Java API'': Recursively create a descendant’s path by appending all child names.
|
||||||
|
*/
|
||||||
|
def descendant(names: java.lang.Iterable[String]): ActorPath = {
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
/(names.asScala)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sequence of names for this path from root to this. Performance implication: has to allocate a list.
|
||||||
*/
|
*/
|
||||||
def elements: Iterable[String]
|
def elements: Iterable[String]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ''Java API'': Sequence of names for this path from root to this. Performance implication: has to allocate a list.
|
||||||
|
*/
|
||||||
|
def getElements: java.lang.Iterable[String] = {
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
elements.asJava
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk up the tree to obtain and return the RootActorPath.
|
* Walk up the tree to obtain and return the RootActorPath.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ private[akka] abstract class InternalActorRef extends ActorRef with ScalaActorRe
|
||||||
* trailing "" element must be disregarded. If the requested path does not
|
* trailing "" element must be disregarded. If the requested path does not
|
||||||
* exist, return Nobody.
|
* exist, return Nobody.
|
||||||
*/
|
*/
|
||||||
def getChild(name: Iterable[String]): InternalActorRef
|
def getChild(name: Iterator[String]): InternalActorRef
|
||||||
}
|
}
|
||||||
|
|
||||||
private[akka] case object Nobody extends MinimalActorRef {
|
private[akka] case object Nobody extends MinimalActorRef {
|
||||||
|
|
@ -256,26 +256,27 @@ class LocalActorRef private[akka] (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getChild(names: Iterable[String]): InternalActorRef = {
|
def getChild(names: Iterator[String]): InternalActorRef = {
|
||||||
/*
|
/*
|
||||||
* The idea is to recursively descend as far as possible with LocalActor
|
* The idea is to recursively descend as far as possible with LocalActor
|
||||||
* Refs and hand over to that “foreign” child when we encounter it.
|
* Refs and hand over to that “foreign” child when we encounter it.
|
||||||
*/
|
*/
|
||||||
@tailrec
|
@tailrec
|
||||||
def rec(ref: InternalActorRef, name: Iterable[String]): InternalActorRef = ref match {
|
def rec(ref: InternalActorRef, name: Iterator[String]): InternalActorRef =
|
||||||
case l: LocalActorRef ⇒
|
ref match {
|
||||||
val n = name.head
|
case l: LocalActorRef ⇒
|
||||||
val rest = name.tail
|
val n = name.next()
|
||||||
val next = n match {
|
val next = n match {
|
||||||
case ".." ⇒ l.getParent
|
case ".." ⇒ l.getParent
|
||||||
case "" ⇒ l
|
case "" ⇒ l
|
||||||
case _ ⇒ l.getSingleChild(n)
|
case _ ⇒ l.getSingleChild(n)
|
||||||
}
|
}
|
||||||
if (next == Nobody || rest.isEmpty) next else rec(next, rest)
|
if (next == Nobody || name.isEmpty) next else rec(next, name)
|
||||||
case _ ⇒
|
case _ ⇒
|
||||||
ref.getChild(name)
|
ref.getChild(name)
|
||||||
}
|
}
|
||||||
rec(this, names)
|
if (names.isEmpty) this
|
||||||
|
else rec(this, names)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========= AKKA PROTECTED FUNCTIONS =========
|
// ========= AKKA PROTECTED FUNCTIONS =========
|
||||||
|
|
@ -326,9 +327,11 @@ case class SerializedActorRef(path: String) {
|
||||||
trait MinimalActorRef extends InternalActorRef {
|
trait MinimalActorRef extends InternalActorRef {
|
||||||
|
|
||||||
def getParent: InternalActorRef = Nobody
|
def getParent: InternalActorRef = Nobody
|
||||||
def getChild(name: Iterable[String]): InternalActorRef =
|
def getChild(names: Iterator[String]): InternalActorRef = {
|
||||||
if (name.size == 1 && name.head.isEmpty) this
|
val dropped = names.dropWhile(_.isEmpty)
|
||||||
|
if (dropped.isEmpty) this
|
||||||
else Nobody
|
else Nobody
|
||||||
|
}
|
||||||
|
|
||||||
//FIXME REMOVE THIS, ticket #1416
|
//FIXME REMOVE THIS, ticket #1416
|
||||||
//FIXME REMOVE THIS, ticket #1415
|
//FIXME REMOVE THIS, ticket #1415
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,7 @@ trait ActorRefFactory {
|
||||||
def actorFor(path: Iterable[String]): ActorRef = provider.actorFor(lookupRoot, path)
|
def actorFor(path: Iterable[String]): ActorRef = provider.actorFor(lookupRoot, path)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look-up an actor by applying the given path elements, starting from the
|
* ''Java API'': Look-up an actor by applying the given path elements, starting from the
|
||||||
* current context, where `".."` signifies the parent of an actor.
|
* current context, where `".."` signifies the parent of an actor.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
|
|
@ -307,7 +307,7 @@ trait ActorRefFactory {
|
||||||
*
|
*
|
||||||
* For maximum performance use a collection with efficient head & tail operations.
|
* For maximum performance use a collection with efficient head & tail operations.
|
||||||
*/
|
*/
|
||||||
def actorFor(path: java.util.List[String]): ActorRef = {
|
def actorFor(path: java.lang.Iterable[String]): ActorRef = {
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
provider.actorFor(lookupRoot, path.asScala)
|
provider.actorFor(lookupRoot, path.asScala)
|
||||||
}
|
}
|
||||||
|
|
@ -462,13 +462,17 @@ class LocalActorRefProvider(
|
||||||
val children = new ConcurrentHashMap[String, AskActorRef]
|
val children = new ConcurrentHashMap[String, AskActorRef]
|
||||||
def path = tempNode
|
def path = tempNode
|
||||||
override def getParent = rootGuardian
|
override def getParent = rootGuardian
|
||||||
override def getChild(name: Iterable[String]): InternalActorRef = {
|
override def getChild(name: Iterator[String]): InternalActorRef = {
|
||||||
children.get(name.head) match {
|
if (name.isEmpty) this
|
||||||
case null ⇒ Nobody
|
else {
|
||||||
case some ⇒
|
val n = name.next()
|
||||||
val t = name.tail
|
if (n.isEmpty) this
|
||||||
if (t.isEmpty) some
|
else children.get(n) match {
|
||||||
else some.getChild(t)
|
case null ⇒ Nobody
|
||||||
|
case some ⇒
|
||||||
|
if (name.isEmpty) some
|
||||||
|
else some.getChild(name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -497,7 +501,7 @@ class LocalActorRefProvider(
|
||||||
|
|
||||||
def actorFor(ref: InternalActorRef, path: Iterable[String]): InternalActorRef =
|
def actorFor(ref: InternalActorRef, path: Iterable[String]): InternalActorRef =
|
||||||
if (path.isEmpty) deadLetters
|
if (path.isEmpty) deadLetters
|
||||||
else ref.getChild(path) match {
|
else ref.getChild(path.iterator) match {
|
||||||
case Nobody ⇒ deadLetters
|
case Nobody ⇒ deadLetters
|
||||||
case x ⇒ x
|
case x ⇒ x
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,11 +218,24 @@ abstract class ActorSystem extends ActorRefFactory {
|
||||||
*/
|
*/
|
||||||
def /(name: String): ActorPath
|
def /(name: String): ActorPath
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ''Java API'': Create a new child actor path.
|
||||||
|
*/
|
||||||
|
def child(child: String): ActorPath = /(child)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a path below the application guardian to be used with [[ActorSystem.actorFor]].
|
* Construct a path below the application guardian to be used with [[ActorSystem.actorFor]].
|
||||||
*/
|
*/
|
||||||
def /(name: Iterable[String]): ActorPath
|
def /(name: Iterable[String]): ActorPath
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ''Java API'': Recursively create a descendant’s path by appending all child names.
|
||||||
|
*/
|
||||||
|
def descendant(names: java.lang.Iterable[String]): ActorPath = {
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
/(names.asScala)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start-up time in milliseconds since the epoch.
|
* Start-up time in milliseconds since the epoch.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ private[akka] case class RemoteActorRef private[akka] (
|
||||||
|
|
||||||
// FIXME RK
|
// FIXME RK
|
||||||
def getParent = Nobody
|
def getParent = Nobody
|
||||||
def getChild(name: Iterable[String]) = Nobody
|
def getChild(name: Iterator[String]) = Nobody
|
||||||
|
|
||||||
@volatile
|
@volatile
|
||||||
private var running: Boolean = true
|
private var running: Boolean = true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue